我在使用Spring和Wiremock进行集成测试时遇到了一个非常奇怪的情况:突然,一个特定的测试开始间歇性地失败。下面是错误的片段:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:10314/my/endpoint": Software caused connection abort: recv failed; nested exception is java.net.SocketException: Software caused connection abort: recv failed
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:468) ~[spring-web-5.3.7.jar:5.3.7]
... more logs here ...
上下文如下:我添加了一个新的测试,它使用wiremock来存根响应:
wireMockServer.stubFor(WireMock.post("/my/endpoint")
.withRequestBody(containing(aJsonRequestBodyHere))
.willReturn(aResponse()
.withBody(aJsonResponseHere)
.withStatus(HttpStatus.OK.value())
.withHeader(HttpHeader.CONTENT_TYPE.toString(), CONTENT_TYPE_APPLICATION_JSON)));
对该存根端点的调用如下所示:
given()
.when()
.get("my/endpoint")
.then()
.body(containsString(theExpectedJsonResponse)))
.statusCode(200);
奇怪之处:
- 同样的测试在我的本地机器上运行没有任何问题-如果单独运行
- 在我的机器上运行所有测试时,有时相同的测试会失败,有时不会
- 只有这个测试每次都失败;无其他测试失败
- 当在Jenkins上运行测试时,它会100%失败
4条答案
按热度按时间jtw3ybtb1#
在对此进行了一些挖掘之后,我发现了this和this文章,它们几乎100%地描述了我的情况。
根本原因似乎是测试执行得太快-可能是那些没有做太多事情的测试-Wiremock没有时间为下一个测试正确设置。我已经通过在测试开始时添加
Thread.sleep(2000)
来测试这个假设,然后运行所有测试多次-所有测试都通过了,没有问题。解以the first article表示:注册一个Transformer类,它将拦截所有响应并向它们添加
Connection=close
头。详情:我添加了一个
Transformer
类,它扩展了ResponseDefinitionTransformer
,并在每个响应上添加了Connection
头。Transformer类(取自the first article):
配置类:
qojgxg4l2#
TL;DR
在响应上使用
.withHeader(HttpHeaders.CONNECTION, "close")
的解决方法修复了以下问题:使用com.github.tomakehurst:wiremock:2.27.2和com.github.tomakehurst:wiremock-jre 8:2.30.1进行测试
7tofc5zh3#
在使用WireMock服务器通过Feign客户端发送请求时,在集成测试中遇到了同样的问题。
根据Tom在前面的回答中的评论,决定修复客户端的配置,以便假装重试发送请求。找到了this文章中描述的解决方案。
Feign最简单的方法是添加
@Configuration
类,其中包含feign.Retryer
@Bean
:fv2wmkja4#
从这个帖子中,他们推荐了以下对我有效的解决方法:
只需使用
.withHeader(HttpHeaders.CONNECTION, "close")
覆盖每个存根的默认keep-alive连接行为。