MockRestServiceServer如何仅验证请求路径(排除查询字符串)
问题原因
Spring Boot 2.6.0对应的Spring Test版本中,MockRestRequestMatchers.requestTo()的字符串入参重载默认执行完整URL匹配,会把查询字符串也纳入校验范围,所以你传入不带查询参数的路径时会匹配失败。
最优解决方案
自定义Hamcrest Matcher,仅校验URI的scheme、host、port、path核心部分,忽略查询参数和锚点,完全满足路径精确匹配的需求,同时把查询参数的校验交给专门的queryParam()方法处理:
步骤1:定义通用路径匹配Matcher
import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import java.net.URI; import java.net.URISyntaxException; import java.util.Objects; public class UriPathMatcher extends BaseMatcher<String> { private final String expectedBaseUri; private UriPathMatcher(String expectedBaseUri) { this.expectedBaseUri = expectedBaseUri; } public static UriPathMatcher uriPathEquals(String expectedBaseUri) { return new UriPathMatcher(expectedBaseUri); } @Override public boolean matches(Object actual) { if (!(actual instanceof String actualUrl)) return false; try { URI actualUri = new URI(actualUrl); URI expectedUri = new URI(expectedBaseUri); return Objects.equals(actualUri.getScheme(), expectedUri.getScheme()) && Objects.equals(actualUri.getHost(), expectedUri.getHost()) && actualUri.getPort() == expectedUri.getPort() && Objects.equals(actualUri.getPath(), expectedUri.getPath()); } catch (URISyntaxException e) { return false; } } @Override public void describeTo(Description description) { description.appendText("URI path equals to: " + expectedBaseUri); } }
步骤2:修改测试代码调用Matcher
import static 你的包名.UriPathMatcher.uriPathEquals; @Test void testApiCall() { mockRestServiceServer.expect(MockRestRequestMatchers.requestTo(uriPathEquals(OBJECT_ID_URI))) .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) .andExpect(MockRestRequestMatchers.queryParam("keyid", CoreMatchers.anything())) .andExpect(MockRestRequestMatchers.queryParam("token", CoreMatchers.anything())) .andRespond(MockRestResponseCreators.withSuccess("dummy", MediaType.APPLICATION_JSON)); String response = dataApiClientImpl.getItem("asdf12345", "test-obj-id"); Assertions.assertThat(response).isNotNull(); }
为什么queryParam()仍然有用
如果直接用完整URL带查询参数做匹配,会被查询参数的顺序、编码格式影响校验结果,比如参数顺序是keyid在前还是token在前就会导致匹配失败。而queryParam()会自动解析所有查询参数,不关心参数顺序,还可以单独校验每个参数的取值规则,比全URL匹配的灵活性和可读性高很多。
临时替代方案(不推荐)
如果不想自定义Matcher,也可以直接用Hamcrest的组合Matcher实现精确路径匹配,避免startsWith的模糊匹配问题:
mockRestServiceServer.expect(MockRestRequestMatchers.requestTo( CoreMatchers.allOf( CoreMatchers.startsWith(OBJECT_ID_URI), CoreMatchers.either(CoreMatchers.endsWith(OBJECT_ID_URI)) .or(CoreMatchers.containsString(OBJECT_ID_URI + "?")) ) ))
内容的提问来源于stack exchange,提问作者madhav-turangi
相关产品推荐
相关产品推荐

