➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
Docker 基本操作Java 測試(四):PowerMock

Java 測試(五):WireMock

Continued from previous post:
Java 測試(一):簡介

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}