Jonit5 中的 jsonPath 转换问题 spring 使用 MockMVC 启动
jsonPath cast issue in Junit5 spring boot with MockMVC
我有下面的测试用例,导入为
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.assertj.core.internal.bytebuddy.matcher.ElementMatchers.is;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@Test
@DisplayName("Should return product based on the specified Id")
void shouldReturnProductBasedOnTheSpecifiedId() throws Exception {
String Id = java.util.UUID.randomUUID().toString();
ProductViewModel productViewModel = new ProductViewModel(Id, "Product 1", 100, "Product 1 description", 0);
doReturn(productViewModel).when(productService).findById(Id);
mockMvc.perform(get(String.format("/api/v1/product/%s", Id)))
//Validate the response code and content type
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
//validate the headers
.andExpect(header().string(HttpHeaders.ETAG, String.format("\"%s\"", Id)))
.andExpect(header().string(HttpHeaders.LOCATION, String.format("/%s", Id)))
//Validate the return fields
.andExpect(jsonPath("$.id", is(Id)));
//.andExpect((ResultMatcher) jsonPath("$.name", is("Product 1")))
//.andExpect((ResultMatcher) jsonPath("$.price", is(100)))
//.andExpect((ResultMatcher) jsonPath("$.description", is("Product 1 description")))
//.andExpect((ResultMatcher) jsonPath("$.version", is(0)));
}
获取错误为
如果我投射对象,我会收到一条投射错误消息。
有几种方法可以解决:
包括个人 Json 属性比较
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.hamcrest.core.Is.is;
mockMvc.perform(get(String.format("/api/v1/product/%s", Id))
.andExpect(content().contentType(APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.id", is(Id)));
与您的示例的区别在于“是导入”。
将 Json 响应反序列化为 class 并比较对象
这是一种更通用、可重复使用的方法。
- 使用 Json 反序列化方法将其转换为 well-known class 实例的对象。
- 在测试中将预期的对象与接收到的对象进行比较。
你可以在下面link看到一个完整的例子,更具体的在测试中:
static Stream<Arguments> findByIdWithOrderLines_validIdTestCases() {
PizzaDto pizzaDto = new PizzaDto((short)1, "Carbonara", 7.50);
OrderLineDto orderLineDto = new OrderLineDto(10, 1, pizzaDto, (short)2, 15D);
OrderDto dto = new OrderDto(1, "Order 1", new Date(), asList(orderLineDto));
return Stream.of(
//@formatter:off
// serviceResult, expectedResultHttpCode, expectedBodyResult
Arguments.of( empty(), NOT_FOUND, null ),
Arguments.of( of(dto), OK, dto )
); //@formatter:on
}
@ParameterizedTest
@SneakyThrows
@WithMockUser(authorities = {Constants.ROLE_ADMIN})
@MethodSource("findByIdWithOrderLines_validIdTestCases")
@DisplayName("findByIdWithOrderLines: when given Id verifies the validations then the suitable Http code is returned")
public void findByIdWithOrderLines_whenGivenIdVerifiesValidations_thenSuitableHttpCodeIsReturned(Optional<OrderDto> serviceResult,
HttpStatus expectedResultHttpCode, OrderDto expectedBodyResult) {
// Given
Integer validOrderId = 1;
// When
when(mockOrderService.findByIdWithOrderLines(validOrderId)).thenReturn(serviceResult);
ResultActions result = mockMvc.perform(get(RestRoutes.ORDER.ROOT + "/" + validOrderId + RestRoutes.ORDER.WITH_ORDERLINES));
// Then
result.andExpect(status().is(expectedResultHttpCode.value()));
assertEquals(expectedBodyResult, fromJson(result.andReturn().getResponse().getContentAsString(), OrderDto.class));
verify(mockOrderService, times(1)).findByIdWithOrderLines(validOrderId);
}
我有下面的测试用例,导入为
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.assertj.core.internal.bytebuddy.matcher.ElementMatchers.is;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@Test
@DisplayName("Should return product based on the specified Id")
void shouldReturnProductBasedOnTheSpecifiedId() throws Exception {
String Id = java.util.UUID.randomUUID().toString();
ProductViewModel productViewModel = new ProductViewModel(Id, "Product 1", 100, "Product 1 description", 0);
doReturn(productViewModel).when(productService).findById(Id);
mockMvc.perform(get(String.format("/api/v1/product/%s", Id)))
//Validate the response code and content type
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
//validate the headers
.andExpect(header().string(HttpHeaders.ETAG, String.format("\"%s\"", Id)))
.andExpect(header().string(HttpHeaders.LOCATION, String.format("/%s", Id)))
//Validate the return fields
.andExpect(jsonPath("$.id", is(Id)));
//.andExpect((ResultMatcher) jsonPath("$.name", is("Product 1")))
//.andExpect((ResultMatcher) jsonPath("$.price", is(100)))
//.andExpect((ResultMatcher) jsonPath("$.description", is("Product 1 description")))
//.andExpect((ResultMatcher) jsonPath("$.version", is(0)));
}
获取错误为
如果我投射对象,我会收到一条投射错误消息。
有几种方法可以解决:
包括个人 Json 属性比较
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.hamcrest.core.Is.is;
mockMvc.perform(get(String.format("/api/v1/product/%s", Id))
.andExpect(content().contentType(APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.id", is(Id)));
与您的示例的区别在于“是导入”。
将 Json 响应反序列化为 class 并比较对象
这是一种更通用、可重复使用的方法。
- 使用 Json 反序列化方法将其转换为 well-known class 实例的对象。
- 在测试中将预期的对象与接收到的对象进行比较。
你可以在下面link看到一个完整的例子,更具体的在测试中:
static Stream<Arguments> findByIdWithOrderLines_validIdTestCases() {
PizzaDto pizzaDto = new PizzaDto((short)1, "Carbonara", 7.50);
OrderLineDto orderLineDto = new OrderLineDto(10, 1, pizzaDto, (short)2, 15D);
OrderDto dto = new OrderDto(1, "Order 1", new Date(), asList(orderLineDto));
return Stream.of(
//@formatter:off
// serviceResult, expectedResultHttpCode, expectedBodyResult
Arguments.of( empty(), NOT_FOUND, null ),
Arguments.of( of(dto), OK, dto )
); //@formatter:on
}
@ParameterizedTest
@SneakyThrows
@WithMockUser(authorities = {Constants.ROLE_ADMIN})
@MethodSource("findByIdWithOrderLines_validIdTestCases")
@DisplayName("findByIdWithOrderLines: when given Id verifies the validations then the suitable Http code is returned")
public void findByIdWithOrderLines_whenGivenIdVerifiesValidations_thenSuitableHttpCodeIsReturned(Optional<OrderDto> serviceResult,
HttpStatus expectedResultHttpCode, OrderDto expectedBodyResult) {
// Given
Integer validOrderId = 1;
// When
when(mockOrderService.findByIdWithOrderLines(validOrderId)).thenReturn(serviceResult);
ResultActions result = mockMvc.perform(get(RestRoutes.ORDER.ROOT + "/" + validOrderId + RestRoutes.ORDER.WITH_ORDERLINES));
// Then
result.andExpect(status().is(expectedResultHttpCode.value()));
assertEquals(expectedBodyResult, fromJson(result.andReturn().getResponse().getContentAsString(), OrderDto.class));
verify(mockOrderService, times(1)).findByIdWithOrderLines(validOrderId);
}