Wiremock:如何匹配没有特定 属性 的 JSON 请求?
Wiremock: how to match a JSON request that does NOT have a specific property?
我正在尝试模拟一个 API 调用,该调用在 POST 中接受一个 JSON 主体,它有两种可能的响应:
- 如果正文包含
SearchCenter
属性,请回答 A
- 如果正文不包含
SearchCenter
,请使用响应 B 进行回答
在 Wiremock 文档的 Request Matching 章节中,它只展示了如何 积极地 匹配 JSON,它没有展示如何匹配缺失的属性。
带有 SearchCenter
的示例请求:
{
"GeoCoordinatesResponseFormat": "DecimalDegree",
"ProviderID": "bla bla",
"SearchCenter": {
"GeoCoordinates": {
"DecimalDegree": {
"Latitude": "{{search_lat}}",
"Longitude": "{{search_lon}}"
}
},
"Radius": {{search_radius}}
}
}
没有 SearchCenter
的示例请求:
{
"GeoCoordinatesResponseFormat": "DecimalDegree",
"ProviderID": "bla bla"
}
编辑:我可能已经超前了——我认为有一个更简单的匹配解决方案。您可以使用 negative matching with regex。 (Negative Lookahead) 我仍然认为我更喜欢优先级方法。
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(matchingJsonPath("$.?!SearchCenter"))
.willReturn(ok("Body does not contain Search Center"));
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(matchingJsonPath("$.SearchCenter"))
.willReturn(ok("Body does contain Search Center"));
您可以通过两种方式完成此操作。第一个将使用正则表达式 matcher/not 匹配器。假设您使用的是存根...
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(notMatching("\"SearchCenter\": \{ .* \}"))
.willReturn(ok("Body does not contain Search Center"));
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(matchingJsonPath("$.SearchCenter"))
.willReturn(ok("Body does contain Search Center"));
这会在不匹配时进行正则表达式匹配以检查该字段是否不存在,然后JSON 路径匹配以检查该字段是否存在。 (我没有测试实际代码,所以正则表达式匹配 / JSON 路径可能需要一些调整。)
不过,我认为更好的解决方案是让一个响应更具体地匹配 return,而另一个响应更不具体地匹配 return。我们可以通过优先级来实现这一点。
stubFor(any(urlPathEqualTo("/some-endpoint"))
.atPriority(1)
.withRequestBody(matchingJsonPath("$.SearchCenter"))
.willReturn(ok("Body does contain Search Center"));
stubFor(any(urlPathEqualTo("/some-endpoint"))
.atPriority(2)
.willReturn(ok("Body does not contain Search Center"));
Information on Priorities can be found here。 Priorities 上的 tl;dr 是它们强制 WireMock 在其他匹配项之前检查某些匹配项。在这种情况下,我们将检查请求正文是否包含我们想要的字段 ("Search Center"),如果包含,我们将 return 匹配。如果我们有其他具有相同优先级 (1) 的存根,那么在进入下一个优先级之前也会检查这些存根。如果没有找到我们要匹配的字段,我们将转到下一个优先级。因为 Priority 2 的存根不需要匹配 Request Body 中的 JSON Path,所以我们会匹配
我更喜欢两次特定匹配的优先级,这仅仅是因为我喜欢 "fallback" 通用存根提供的行为,其中对“/some-endpoint”的任何调用都将通过通用响应来实现。
为了匹配缺失的 JSON 属性,您可以将 matchingJsonPath
运算符与 absent()
结合使用,如下所示:
.withRequestBody(matchingJsonPath("$.SearchCenter", absent()))
我正在尝试模拟一个 API 调用,该调用在 POST 中接受一个 JSON 主体,它有两种可能的响应:
- 如果正文包含
SearchCenter
属性,请回答 A - 如果正文不包含
SearchCenter
,请使用响应 B 进行回答
在 Wiremock 文档的 Request Matching 章节中,它只展示了如何 积极地 匹配 JSON,它没有展示如何匹配缺失的属性。
带有 SearchCenter
的示例请求:
{
"GeoCoordinatesResponseFormat": "DecimalDegree",
"ProviderID": "bla bla",
"SearchCenter": {
"GeoCoordinates": {
"DecimalDegree": {
"Latitude": "{{search_lat}}",
"Longitude": "{{search_lon}}"
}
},
"Radius": {{search_radius}}
}
}
没有 SearchCenter
的示例请求:
{
"GeoCoordinatesResponseFormat": "DecimalDegree",
"ProviderID": "bla bla"
}
编辑:我可能已经超前了——我认为有一个更简单的匹配解决方案。您可以使用 negative matching with regex。 (Negative Lookahead) 我仍然认为我更喜欢优先级方法。
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(matchingJsonPath("$.?!SearchCenter"))
.willReturn(ok("Body does not contain Search Center"));
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(matchingJsonPath("$.SearchCenter"))
.willReturn(ok("Body does contain Search Center"));
您可以通过两种方式完成此操作。第一个将使用正则表达式 matcher/not 匹配器。假设您使用的是存根...
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(notMatching("\"SearchCenter\": \{ .* \}"))
.willReturn(ok("Body does not contain Search Center"));
stubFor(any(urlPathEqualTo("/some-endpoint"))
.withRequestBody(matchingJsonPath("$.SearchCenter"))
.willReturn(ok("Body does contain Search Center"));
这会在不匹配时进行正则表达式匹配以检查该字段是否不存在,然后JSON 路径匹配以检查该字段是否存在。 (我没有测试实际代码,所以正则表达式匹配 / JSON 路径可能需要一些调整。)
不过,我认为更好的解决方案是让一个响应更具体地匹配 return,而另一个响应更不具体地匹配 return。我们可以通过优先级来实现这一点。
stubFor(any(urlPathEqualTo("/some-endpoint"))
.atPriority(1)
.withRequestBody(matchingJsonPath("$.SearchCenter"))
.willReturn(ok("Body does contain Search Center"));
stubFor(any(urlPathEqualTo("/some-endpoint"))
.atPriority(2)
.willReturn(ok("Body does not contain Search Center"));
Information on Priorities can be found here。 Priorities 上的 tl;dr 是它们强制 WireMock 在其他匹配项之前检查某些匹配项。在这种情况下,我们将检查请求正文是否包含我们想要的字段 ("Search Center"),如果包含,我们将 return 匹配。如果我们有其他具有相同优先级 (1) 的存根,那么在进入下一个优先级之前也会检查这些存根。如果没有找到我们要匹配的字段,我们将转到下一个优先级。因为 Priority 2 的存根不需要匹配 Request Body 中的 JSON Path,所以我们会匹配
我更喜欢两次特定匹配的优先级,这仅仅是因为我喜欢 "fallback" 通用存根提供的行为,其中对“/some-endpoint”的任何调用都将通过通用响应来实现。
为了匹配缺失的 JSON 属性,您可以将 matchingJsonPath
运算符与 absent()
结合使用,如下所示:
.withRequestBody(matchingJsonPath("$.SearchCenter", absent()))