Resteasy集成测试中WireMock未捕获Trustpilot API请求问题排查
问题根源分析
你遇到的核心问题是:你的MyResource仍然在向真实的Trustpilot API发送请求,而非WireMock的模拟服务,所以WireMock自然捕获不到请求记录。虽然你启动了WireMock并配置了动态端口,但代码里硬编码的Trustpilot API域名并没有指向WireMock运行的localhost地址。
修复步骤
1. 让Trustpilot API URL可配置
首先要修改MyResource,把硬编码的第三方API地址改成可注入的配置项,这样测试时能替换成WireMock的地址。
修改MyResource代码:
import javax.inject.Inject; import javax.inject.Named; public class MyResource { // 替换硬编码URL为可注入的配置 @Inject @Named("trustpilotApiBaseUrl") private String trustpilotApiBaseUrl; // 构建请求时使用这个可配置的base URL private URI buildTrustpilotRequestUri(String businessUnitId) { return UriBuilder.fromUri(trustpilotApiBaseUrl) .path("/v1/private/product-reviews/business-units/{businessUnitId}/invitation-links") .build(businessUnitId); } }
然后在测试配置类MyResourceTestContext中,注入WireMock的运行地址:
import com.github.tomakehurst.wiremock.WireMockRule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyResourceTestContext { @Bean @Named("trustpilotApiBaseUrl") public String trustpilotApiBaseUrl(WireMockRule wireMockRule) { // 应用用HTTPS调用就用httpsPort(),HTTP则用port() return "https://localhost:" + wireMockRule.httpsPort(); } // 其他Bean配置... }
2. 修正WireMock的Stub与验证逻辑
WireMock匹配请求时不需要完整域名和端口,只需要匹配相对路径即可(因为请求现在发往localhost的WireMock端口)。你之前用完整URI创建stub和验证,会导致匹配失败。
修改测试代码中的stub和验证部分:
// 改用相对路径匹配 String trustpilotRelativePath = "/v1/private/product-reviews/business-units/" + BUSINESS_UNIT_ID + "/invitation-links"; // 创建Stub stubFor(post(urlEqualTo(trustpilotRelativePath)) .willReturn(okJson("{\"reviewLinkId\":\"" + REVIEW_LINK_ID + "\"," + "\"reviewUrl\":\"" + expectedRedirectURI.toString() + "\"}"))); // 验证请求 WireMock.verify(1, postRequestedFor(urlEqualTo(trustpilotRelativePath)));
3. 处理HTTPS证书信任问题
WireMock默认使用自签名HTTPS证书,Resteasy客户端会拒绝连接。需要配置客户端忽略SSL证书验证:
在测试配置中添加忽略SSL的Resteasy客户端Bean:
import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.SecureRandom; import java.security.cert.X509Certificate; @Bean public ResteasyClient resteasyClient() throws Exception { // 创建信任所有证书的TrustManager TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom()); // 构建忽略SSL验证的客户端 return new ResteasyClientBuilder() .sslContext(sslContext) .hostnameVerifier((hostname, session) -> true) .build(); }
4. 修复代码笔误
你构建apiRequestURI时,路径里多了一个闭合大括号:
.fromUri("https://api.trustpilot.com/v1/private/product-reviews/business-units" + "/{businessUnitId}}/invitation-links")
把{businessUnitId}}改成{businessUnitId},避免生成错误URL。
验证修复效果
完成以上修改后重新运行测试:
MyResource会向WireMock的HTTPS端口发送请求- WireMock会捕获请求并返回预设响应
- 验证逻辑会匹配到相对路径的请求,不再抛出
VerificationException
内容的提问来源于stack exchange,提问作者P.Raber
相关产品推荐
相关产品推荐

