Spring Boot中MockMvc的JsonPath配置及表达式假阳性问题
JsonPath配置与表达式问题解答
一、JsonPath原生配置方式
JsonPath本身可通过如下代码配置:
import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Option; // ... Configuration configuration = Configuration .builder() .options(Option.REQUIRE_PROPERTIES) .build(); JsonPath .using(configuration) .parse(someJson) .read("$.*.bar");
该示例启用了Option.REQUIRE_PROPERTIES配置项,当指定路径不存在时会直接抛出异常。
二、Spring Boot MockMvc中配置JsonPath的REQUIRE_PROPERTIES
Spring MockMvc默认的jsonPath匹配器未直接开放JsonPath配置入口,可通过自定义ResultMatcher实现需求:
自定义匹配工具类
import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Option; import org.springframework.test.web.servlet.ResultMatcher; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.hamcrest.MatcherAssert.assertThat; public class CustomJsonPathMatchers { // 预先配置好需要的JsonPath规则 private static final Configuration CONFIG = Configuration.builder() .options(Option.REQUIRE_PROPERTIES) .build(); public static ResultMatcher jsonPathWithConfig(String expression, org.hamcrest.Matcher<?> matcher) { return content().string(jsonContent -> { // 使用自定义配置解析JSON并提取结果 Object result = JsonPath.using(CONFIG).parse(jsonContent).read(expression); // 用Hamcrest匹配器验证结果 assertThat(result, matcher); return true; }); } }
在测试中使用
import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static com.yourpackage.CustomJsonPathMatchers.jsonPathWithConfig; import static org.hamcrest.Matchers.isEmptyCollection; // ... mockMvc .perform(get("/test")) .andExpect(status().isOk()) .andExpect(jsonPathWithConfig("$.*.bar", isEmptyCollection()));
三、JsonPath表达式假阳性问题解决
场景说明
输入JSON:
[ {"animal": "cat", "meow": true}, {"animal": "cat", "meow": true}, {"animal": "cat", "bark": true} ]
原表达式jsonPath("$.[?(@.animal == 'cat')].meow").value(everyItem(equalTo(true)))出现假阳性,原因是第三个对象无meow字段,JsonPath会返回null,部分场景下匹配器未正确识别null与true的差异。
正确写法
方法1:JsonPath层面直接过滤验证
直接在表达式中同时过滤animal为cat和meow等于true的条件,再验证结果数量与总cat数量一致:
import static org.hamcrest.Matchers.hasSize; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; // 验证总共有3个cat mockMvc.perform(get("/test")) .andExpect(jsonPath("$.[?(@.animal == 'cat')]").value(hasSize(3))) // 验证所有cat都满足meow为true(结果数量需等于3才通过) .andExpect(jsonPath("$.[?(@.animal == 'cat' && @.meow == true)]").value(hasSize(3)));
方法2:结合匹配器排除null值
如果需要保留原表达式结构,可通过Hamcrest的组合匹配器同时验证所有元素为true且无null值:
import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.nullValue; mockMvc.perform(get("/test")) .andExpect(jsonPath("$.[?(@.animal == 'cat')].meow") .value(allOf( everyItem(equalTo(true)), not(hasItem(nullValue())) )));
内容的提问来源于stack exchange,提问作者István Béksy
相关产品推荐
相关产品推荐

