Pact Test消费者端生成契约时出现connection refused连接拒绝错误
Pact消费者契约测试连接拒绝问题排查
问题背景
在消费者端运行Pact契约测试生成契约文件时,持续触发连接拒绝错误,测试用例执行失败,相关代码、配置及错误信息如下:
测试类代码
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = "product-service.products.baseUrl:http://localhost:9001/svc-product-service/api/products") public class ProductServiceContractTest { @Autowired private ProductService productService; @Rule public PactProviderRuleMk2 provider = new PactProviderRuleMk2("svc-product-service", "localhost", 9001, this); @Pact(consumer = "svc-product-order-service") public RequestResponsePact pactProductExists(PactDslWithProvider builder) { return builder.given("Product 1001 exists").uponReceiving("A request to /1001").path("/1001").method("GET") .willRespondWith().status(200) .body(new PactDslJsonBody().integerType("id", 1001).stringType("name", "Laptop")) .toPact(); } @PactVerification(fragment = "pactProductExists") @Test public void productExists() { final Product product = productService.fetchProductsById(1001); assertThat(product.getId()).isEqualTo(1001); assertThat(product.getName()).isEqualTo("Laptop"); } }
Maven依赖配置
<dependency> <groupId>au.com.dius</groupId> <artifactId>pact-jvm-consumer-java8_2.12</artifactId> <version>3.5.24</version> <scope>test</scope> </dependency>
错误堆栈
[ERROR] com.example.product.order.service.ProductServiceContractTest.productExists Time elapsed: 0.034 s <<< ERROR! org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:9001/svc-product-service/api/products/1001": Connect to localhost:9001 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect; nested exception is org.apache.http.conn.HttpHostConnectException: Connect to localhost:9001 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect at com.example.product.order.service.ProductServiceContractTest.productExists(ProductServiceContractTest.java:79) Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:9001 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect at com.example.product.order.service.ProductServiceContractTest.productExists(ProductServiceContractTest.java:79) Caused by: java.net.ConnectException: Connection refused: connect at com.example.product.order.service.ProductServiceContractTest.productExists(ProductServiceContractTest.java:79)
错误核心表现:测试执行时向配置的服务地址发起GET请求,连接localhost:9001端口失败,抛出Connection refused异常导致测试用例失败。
根因分析
连接拒绝错误本质是目标端口没有进程监听,或者请求被路由到了未绑定服务的网络地址,结合代码和错误日志,常见触发原因有三类:
- Junit Rule未正常生效,Pact内置的Mock服务没有启动,9001端口无服务监听
- 本机IPv6解析优先级高于IPv4,Pact Mock服务默认绑定IPv4回环地址,请求被路由到IPv6地址导致连接失败
- 等连接问题修复后,现有代码还存在路径不匹配问题:Pact交互定义的请求路径为
/1001,但实际业务代码请求的完整路径为/svc-product-service/api/products/1001,会触发Pact的请求匹配失败
排查解决步骤
- 检查Junit版本兼容性
你使用的pact-jvm-consumer-java8_2.12:3.5.24是基于Junit4实现的,若项目中混入Junit5(Jupiter)依赖,会导致@Rule注解不生效,Pact Mock服务不会启动。先排查依赖树,排除Junit5相关的测试依赖,确保测试运行时使用Junit4执行。 - 验证Mock服务启动状态
测试执行时,在系统命令行执行端口检查命令:- Windows系统:
netstat -ano | findstr :9001 - Mac/Linux系统:
lsof -i:9001
如果没有查询到9001端口的监听进程,说明Mock服务未启动,优先排查测试运行器配置、@Rule字段的访问修饰符(必须为public)是否符合要求。
- Windows系统:
- 强制使用IPv4网络栈
从错误日志可以看到,localhost解析同时返回了IPv4和IPv6地址,给测试任务添加JVM启动参数-Djava.net.preferIPv4Stack=true,强制客户端使用IPv4地址发起连接,避免路由到未绑定的IPv6地址。 - 修正Pact交互的路径配置
连接问题解决后,将Pact DSL中定义的请求路径从/1001修改为实际请求的完整路径/svc-product-service/api/products/1001,或者在初始化PactProviderRuleMk2时统一设置上下文路径,保证Mock服务的匹配规则和业务代码的实际请求路径一致,避免出现404或请求不匹配错误。 - 校验配置注入正确性
测试启动时打印ProductService中实际使用的baseUrl配置,确认配置值和Pact Mock服务的地址、端口一致,避免配置覆盖导致请求指向未启动的真实服务地址。
内容的提问来源于stack exchange,提问作者Geethu
相关产品推荐
相关产品推荐

