如何在MockMvc中从jsonPath()获取字符串并比较两个jsonPath值
如何在Spring MVC测试中比较两个JSON路径的值
你遇到的问题很典型——jsonPath()方法返回的是JsonPathResultMatchers对象(这就是你看到类名输出的原因),而不是JSON属性的实际值,所以直接把它传给equalTo()肯定不会生效。下面给你几种可行的解决方法:
方法一:提取响应体后手动比较
先获取完整的响应体,再用JsonPath.read()分别读取两个属性的值,最后用断言完成比较:
// 执行请求并获取测试结果 MvcResult result = mockMvc.perform(get(requestURL)) .andReturn(); // 读取响应体的字符串内容 String responseBody = result.getResponse().getContentAsString(); // 用JsonPath分别提取两个属性的实际值 String prop1Value = JsonPath.read(responseBody, "$.prop1"); String prop2Value = JsonPath.read(responseBody, "$.prop2"); // 断言两个值相等 assertEquals(prop1Value, prop2Value);
这种方式直观易懂,还能方便你对提取出的值做额外的逻辑处理。
方法二:在断言中动态提取值
利用Lambda表达式在andExpect中动态获取第一个属性的值,再用它来校验第二个属性:
mockMvc.perform(get(requestURL)) .andExpect(result -> { // 从响应体中提取prop1的实际值 String prop1 = JsonPath.read(result.getResponse().getContentAsString(), "$.prop1"); // 直接断言prop2的值与prop1一致 result.andExpect(jsonPath("$.prop2", equalTo(prop1))); });
这种写法更紧凑,不需要单独保存测试结果对象,适合简单的同响应内属性比较场景。
方法三:自定义Hamcrest匹配器(复用场景)
如果需要多次复用这种“比较两个JSON路径值”的逻辑,可以自定义一个Hamcrest匹配器:
public class JsonPathEqualToMatcher extends TypeSafeMatcher<String> { private final String targetJsonPath; private final String comparedJsonPath; public JsonPathEqualToMatcher(String targetJsonPath, String comparedJsonPath) { this.targetJsonPath = targetJsonPath; this.comparedJsonPath = comparedJsonPath; } @Override protected boolean matchesSafely(String responseBody) { Object targetValue = JsonPath.read(responseBody, targetJsonPath); Object comparedValue = JsonPath.read(responseBody, comparedJsonPath); return Objects.equals(targetValue, comparedValue); } @Override public void describeTo(Description description) { description.appendText("JSON路径 ").appendValue(targetJsonPath) .appendText(" 的值等于路径 ").appendValue(comparedJsonPath).appendText(" 的值"); } public static JsonPathEqualToMatcher equalToJsonPath(String targetJsonPath, String comparedJsonPath) { return new JsonPathEqualToMatcher(targetJsonPath, comparedJsonPath); } }
然后在测试中直接调用:
mockMvc.perform(get(requestURL)) .andExpect(result -> { String responseBody = result.getResponse().getContentAsString(); assertThat(responseBody, equalToJsonPath("$.prop1", "$.prop2")); });
这种方式能让重复的测试逻辑更简洁,适合大型测试用例场景。
注意:如果你的属性是数字、布尔值等非字符串类型,记得调整JsonPath.read()的泛型类型,避免类型转换错误。
内容的提问来源于stack exchange,提问作者Bali
相关产品推荐
相关产品推荐

