Pact消费者测试报错PactMismatchesException:预期请求未被接收
问题排查与解决
核心问题1:Reactor流未触发执行
你代码里创建了Mono<ClientResponse> responseMono但没有触发订阅——Reactor的Mono是冷流,只有调用subscribe()、block()或者其他触发订阅的操作时,才会实际发送HTTP请求。这直接导致Pact的MockServer没收到任何请求,所以抛出"请求未收到"的异常。
修复代码:
在测试方法末尾添加订阅或阻塞操作:
@Test @PactTestFor(pactMethod = "getHealthCheck") void getHealthData(MockServer mockServer) { WebClient webClient=WebClient.builder().baseUrl(mockServer.getUrl()).build(); final String callChainId="a4275861-f60a-44ab-85a6-c0c2c9df5e27"; ThreadContext.put(CallChainIdService.HEADER_NAME, callChainId); AsyncClient asyncClient=new AsyncClient(webClient); Mono<ClientResponse> responseMono=asyncClient.getHealthCheck(); // 触发请求执行,测试场景下用block()同步等待结果更稳妥 ClientResponse response = responseMono.block(); // 也可以用subscribe异步执行,但需确保测试等待请求完成 // responseMono.subscribe(); }
核心问题2:请求头不匹配
你的Pact契约里定义了请求必须携带Content-Type: text/plain头,但实际AsyncClient的get方法只设置了Accept头,没有设置Content-Type请求头。这会导致Pact的请求匹配失败,即使发送了请求也会被判定为不符合契约。
修复AsyncClient的get方法:
添加contentType()设置请求头:
private Mono<ClientResponse> get(MediaType contentType, String uri, Object... params) { return CLIENT .mutate() .defaultHeader(CallChainIdService.HEADER_NAME, ThreadContext.get(CallChainIdService.HEADER_NAME)) .build() .get() .uri(uri, params) .accept(contentType) .contentType(contentType) // 新增这行,匹配契约定义的请求头 .exchange(); }
次要问题:WebClient的exchange方法废弃
如果你的Spring WebFlux版本是5.3及以上,exchange()方法已经被标记为废弃,推荐使用exchangeToMono替代,避免潜在的资源泄漏问题:
private Mono<ClientResponse> get(MediaType contentType, String uri, Object... params) { return CLIENT .mutate() .defaultHeader(CallChainIdService.HEADER_NAME, ThreadContext.get(CallChainIdService.HEADER_NAME)) .build() .get() .uri(uri, params) .accept(contentType) .contentType(contentType) .exchangeToMono(clientResponse -> Mono.just(clientResponse)); // 替代废弃的exchange() }
验证步骤
- 先修复Mono订阅问题,确保请求能正常发送
- 再修复请求头匹配问题,让实际请求的头与契约定义一致
- 重新运行测试,检查Pact是否匹配成功
内容的提问来源于stack exchange,提问作者Hari Hara Prakash Ravi
相关产品推荐
相关产品推荐

