WireMock使用matchingJsonPath带StringValuePattern时抛出空异常问题
问题
我尝试验证发送给下游服务的POST请求体是否包含正确内容/值,但出现空指针异常。
测试代码如下:
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.exactly; import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.verify; @Test void test() throws Exception { mockMvc.perform( post(...) .andExpect(status().isOk()); await().atMost(Duration.ofSeconds(5)).untilAsserted(() -> verify(exactly(1), postRequestedFor(urlPathMatching("my-url-path")) .withRequestBody(matchingJsonPath("$.field1", equalTo("1"))))); }
运行时报错:
com.github.tomakehurst.wiremock.matching.PathPattern$SubExpressionException: Warning: JSON path expression '$.accountId' failed to match document '' because of error 'json string can not be null or empty' Caused by: java.lang.IllegalArgumentException: json string can not be null or empty at wiremock.com.jayway.jsonpath.internal.Utils.notEmpty(Utils.java:401) at wiremock.com.jayway.jsonpath.internal.ParseContextImpl.parse(ParseContextImpl.java:36) at wiremock.com.jayway.jsonpath.JsonPath.read(JsonPath.java:550) at com.github.tomakehurst.wiremock.matching.MatchesJsonPathPattern.getExpressionResult(MatchesJsonPathPattern.java:122) ... 18 more
改用这种表达式映射能正常运行:
.withRequestBody(matchingJsonPath("$.[?(@.field1 == 1)]"))));
我的请求体JSON是:
{ "field1": "1" }
请问正确使用StringValuePattern的方式是什么?
原因分析
报错提示请求体为空字符串,但实际请求体是合法JSON,问题出在WireMock的matchingJsonPath重载方法行为差异:
- 双参数版本
matchingJsonPath(String path, StringValuePattern valuePattern)会先尝试解析请求体为JSON,若请求未携带application/json的Content-Type头,WireMock无法识别请求体格式,会将其当作空字符串处理,触发解析失败。 - 单参数版本
matchingJsonPath(String expression)直接用JsonPath表达式匹配,内部处理逻辑不同,不会触发该解析问题。
正确用法
有三种可靠的解决方式:
方式1:指定请求Content-Type
在匹配规则中添加Content-Type验证,确保WireMock识别请求体为JSON:
verify(exactly(1), postRequestedFor(urlPathMatching("my-url-path")) .withHeader("Content-Type", equalTo("application/json")) .withRequestBody(matchingJsonPath("$.field1", equalTo("1"))));
方式2:使用equalToJson匹配指定字段
若只需验证特定字段,可直接用equalToJson配合忽略额外字段的选项:
verify(exactly(1), postRequestedFor(urlPathMatching("my-url-path")) .withRequestBody(equalToJson("{\"field1\": \"1\"}", true, false)));
第三个参数false表示忽略请求体中除field1外的其他字段。
方式3:用matching替代equalTo
调整值匹配的写法,使用matching适配双参数的matchingJsonPath:
verify(exactly(1), postRequestedFor(urlPathMatching("my-url-path")) .withRequestBody(matchingJsonPath("$.field1", matching("1"))));
内容的提问来源于stack exchange,提问作者noobgrammer
相关产品推荐
相关产品推荐

