如何使用Spring MockMvc与JsonPath测试响应字段的不等性?
解决Spring MVC测试中jsonPath不等于匹配的Mockito异常问题
问题场景
测试接口响应的errorMessage字段不等于特定值时,使用Mockito的AdditionalMatchers.not()配合jsonPath断言,触发了如下异常:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: No matchers found for additional matcher Not(?)
原测试代码:
@Test void whenAnAuth0ExceptionIsThrown_itShouldNotLeakInformation() throws Exception { String description = "Resource not found."; Auth0Exception auth0Exception = new Auth0Exception(description); when(usersService.getRoles()).thenThrow(new UnrecoverableAuthException("api exception", auth0Exception)); mockMvc.perform(get("/v1/users/roles").with(csrf())) .andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.errorMessage").value(AdditionalMatchers.not(description))); verify(usersService).getRoles(); }
问题原因
AdditionalMatchers.not()是Mockito专属的匹配器,而Spring MVC Test的jsonPath().value()方法仅支持Hamcrest匹配器,两者不兼容导致抛出匹配器使用错误。
最优解决方案
改用Hamcrest框架提供的not()匹配器,它可以直接和jsonPath配合使用,无需额外处理:
// 引入Hamcrest的not匹配器 import static org.hamcrest.Matchers.not; @Test void whenAnAuth0ExceptionIsThrown_itShouldNotLeakInformation() throws Exception { String description = "Resource not found."; Auth0Exception auth0Exception = new Auth0Exception(description); when(usersService.getRoles()).thenThrow(new UnrecoverableAuthException("api exception", auth0Exception)); mockMvc.perform(get("/v1/users/roles").with(csrf())) .andExpect(status().isInternalServerError()) // 使用Hamcrest的not匹配器替代Mockito的AdditionalMatchers.not() .andExpect(jsonPath("$.errorMessage").value(not(description))); verify(usersService).getRoles(); }
替代方案(你提到的临时方法)
如果不想依赖Hamcrest,也可以通过MvcResult手动解析响应内容进行断言:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import static org.junit.jupiter.api.Assertions.assertNotEquals; @Test void whenAnAuth0ExceptionIsThrown_itShouldNotLeakInformation() throws Exception { String description = "Resource not found."; Auth0Exception auth0Exception = new Auth0Exception(description); when(usersService.getRoles()).thenThrow(new UnrecoverableAuthException("api exception", auth0Exception)); // 获取请求结果 MvcResult result = mockMvc.perform(get("/v1/users/roles").with(csrf())) .andExpect(status().isInternalServerError()) .andReturn(); // 解析响应JSON String responseBody = result.getResponse().getContentAsString(); JsonNode jsonNode = new ObjectMapper().readTree(responseBody); String errorMessage = jsonNode.get("errorMessage").asText(); // 断言字段不等于目标值 assertNotEquals(description, errorMessage); verify(usersService).getRoles(); }
内容的提问来源于stack exchange,提问作者np_
相关产品推荐
相关产品推荐

