Table of contents
5 WireMock
5.1 Maven dependencies
1<parent>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-parent</artifactId>
4 <version>3.4.5</version>
5</parent>
6
7<dependencies>
8 <dependency>
9 <groupId>org.springframework.boot</groupId>
10 <artifactId>spring-boot-starter-web</artifactId>
11 </dependency>
12
13 <dependency>
14 <groupId>org.springframework.boot</groupId>
15 <artifactId>spring-boot-starter-test</artifactId>
16 <scope>test</scope>
17 </dependency>
18 <dependency>
19 <groupId>org.wiremock.integrations</groupId>
20 <artifactId>wiremock-spring-boot</artifactId>
21 <version>3.10.0</version>
22 <scope>test</scope>
23 </dependency>
24</dependencies>
5.2 寫 Java code
先建立一個典型既 Spring Boot web application。
MyController.java
:
1@RestController
2public class MyController {
3
4 @Autowired
5 @Qualifier("orderRestTemplate")
6 RestTemplate orderService;
7
8 public static record OrderRequest(String testField) {}
9 public static record OrderResponse(Long id, String remarks) {}
10
11 @GetMapping("/test")
12 public OrderResponse getOrder() {
13
14 // XXX hardcoded for simplifying this demo
15 final long orderId = 123L;
16 final OrderRequest reqBody = new OrderRequest("foo");
17
18 // call the order microservice
19 return orderService
20 .exchange("/orders?orderId=" + orderId,
21 HttpMethod.POST, new HttpEntity<>(reqBody), OrderResponse.class)
22 .getBody();
23 }
24}
ApiClientConfig.java
:
1@Configuration
2public class ApiClientConfig {
3
4 @Value("${order-service.uri}")
5 String orderServiceUrl;
6
7 @Bean
8 public RestTemplate orderRestTemplate(RestTemplateBuilder restTemplateBuilder) {
9
10 // XXX hardcoded for simplifying this demo
11 return restTemplateBuilder
12 .rootUri(orderServiceUrl)
13 .basicAuthentication("user", "pass")
14 .build();
15 }
16}
application.yml
:
order-service.uri: http://localhost:8081
之後我地可以寫 test code:
1@EnableWireMock({
2 @ConfigureWireMock(
3 name = "order-service",
4 filesUnderClasspath = "wiremock/my-test-1/order-service",
5 baseUrlProperties = { "order-service.uri" }
6 ),
7})
8@AutoConfigureMockMvc
9@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
10public class MyControllerTest {
11
12 @Autowired MockMvc mockMvc;
13
14 @InjectWireMock("order-service") WireMockServer wiremockOrderService;
15
16 @Test
17 public void test() throws Exception {
18
19 mockMvc.perform(get("/test")
20 .accept(MediaType.APPLICATION_JSON))
21 .andExpect(status().isOk())
22 .andExpect(content().json(
23"""
24{
25 "id": 123,
26 "remarks": "Order 123"
27}
28""", JsonCompareMode.LENIENT));
29
30 wiremockOrderService.verify(1, postRequestedFor(urlEqualTo("/orders?orderId=123")));
31 }
32}
WireMock 支援用 JSON 檔既格式寫 stubbing。
src/test/resources/wiremock/my-test-1/order-service/mappings/orders-by-id.json
:
1{
2 "request": {
3 "method": "POST",
4 "urlPathPattern": "/orders",
5 "queryParameters": {
6 "orderId": { "equalTo": "123" }
7 },
8 "headers": {
9 "Content-Type": { "contains": "application/json" }
10 },
11 "bodyPatterns": [{ "equalToJson": { "testField": "foo" } }]
12 },
13 "response": {
14 "status": 200,
15 "headers": {
16 "Content-Type": "application/json"
17 },
18 "jsonBody": {
19 "id": 123,
20 "remarks": "Order 123"
21 }
22 }
23}