我们有一个Spring Boot 2.2.0.RELEASE应用程序,正在使用WireMock与JUnit 5测试类进行测试。该测试在本地运行良好,但是在我们的Jenkins上,它失败,并显示“地址已在使用中”消息测试成功运行后>]。
这是我们来自pom.xml
的spring依赖项:
<properties> <java.version>11</java.version> <spring-cloud.version>Hoxton.RC2</spring-cloud.version> <spring-cloud-stream.version>3.0.0.RC2</spring-cloud-stream.version> <openapi.codegen.maven.plugin.version>4.1.2</openapi.codegen.maven.plugin.version> <jacoco-maven-plugin.version>0.8.4</jacoco-maven-plugin.version> </properties> <dependencies> <!-- Spring --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-kafka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <!-- Utils --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.openapitools</groupId> <artifactId>openapi-generator</artifactId> <version>${openapi.codegen.maven.plugin.version}</version> </dependency> <!-- Testing --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-wiremock</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> <version>${spring-cloud-stream.version}</version> <type>test-jar</type> <scope>test</scope> <classifier>test-binder</classifier> </dependency> </dependencies>
所以我们的测试非常简单,看起来像这样:
@ExtendWith(SpringExtension.class) @SpringBootTest @ActiveProfiles("test") @AutoConfigureWireMock(port = 0) @Import(TestChannelBinderConfiguration.class) class OurTestClass { @Autowired private OurDataCache cache; @Autowired private InputDestination source; @Autowired private OutputDestination target; @BeforeEach void setupApi() throws IOException, URISyntaxException { stubFor(get("/endpoint") .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE) .withBody(data()) ) ); } @Test void sampleTest() { String messageContent = loadResourceFileAsMessage("messageIn.json"); String expectedOutMessage = loadResourceFileAsMessage("messageOut.json"); Message<byte[]> message = new GenericMessage<>(messageContent.getBytes()); source.send(message); Message<byte[]> received = target.receive(); assertThat(received, notNullValue()); assertThat(new String(received.getPayload()), equalTo(expectedOutMessage.replace(" ", ""))); } }
再次,这在本地运行良好,在詹金斯上,实际的测试用例通过了,但是然后我们得到了错误:
10:29:40 2019-11-25 09:29:40.683 WARN 414 --- [ main] o.s.test.context.TestContextManager : Caught exception while invoking 'afterTestClass' callback on TestExecutionListener [org.springframework.cloud.contract.wiremock.WireMockTestExecutionListener@2b68c59b] for test class [class our.test.Class] 10:29:40 10:29:40 com.github.tomakehurst.wiremock.common.FatalStartupException: java.lang.RuntimeException: java.io.IOException: Failed to bind to /0.0.0.0:12193 10:29:40 at com.github.tomakehurst.wiremock.WireMockServer.start(WireMockServer.java:148) ~[wiremock-jre8-standalone-2.25.1.jar:na] 10:29:40 at org.springframework.cloud.contract.wiremock.WireMockConfiguration.reRegisterServer(WireMockConfiguration.java:137) ~[spring-cloud-contract-wiremock-2.2.0.RC2.jar:2.2.0.RC2] 10:29:40 at org.springframework.cloud.contract.wiremock.WireMockConfiguration.resetMappings(WireMockConfiguration.java:150) ~[spring-cloud-contract-wiremock-2.2.0.RC2.jar:2.2.0.RC2] 10:29:40 at org.springframework.cloud.contract.wiremock.WireMockTestExecutionListener.afterTestClass(WireMockTestExecutionListener.java:76) ~[spring-cloud-contract-wiremock-2.2.0.RC2.jar:2.2.0.RC2] 10:29:40 at org.springframework.test.context.TestContextManager.afterTestClass(TestContextManager.java:488) ~[spring-test-5.2.0.RELEASE.jar:5.2.0.RELEASE] 10:29:40 at org.springframework.test.context.junit.jupiter.SpringExtension.afterAll(SpringExtension.java:86) ~[spring-test-5.2.0.RELEASE.jar:5.2.0.RELEASE] 10:29:40 at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllCallbacks$13(ClassBasedTestDescriptor.java:421) ~[junit-jupiter-engine-5.5.2.jar:5.5.2] 10:29:40 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2] 10:29:40 at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllCallbacks$14(ClassBasedTestDescriptor.java:421) ~[junit-jupiter-engine-5.5.2.jar:5.5.2] 10:29:40 at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na] 10:29:40 at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeAfterAllCallbacks(ClassBasedTestDescriptor.java:421) ~[junit-jupiter-engine-5.5.2.jar:5.5.2] [...] 10:29:40 at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126) ~[surefire-booter-2.22.2.jar:2.22.2] 10:29:40 at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418) ~[surefire-booter-2.22.2.jar:2.22.2] 10:29:40 Caused by: java.lang.RuntimeException: java.io.IOException: Failed to bind to /0.0.0.0:12193 10:29:40 at com.github.tomakehurst.wiremock.jetty9.JettyHttpServer.start(JettyHttpServer.java:184) ~[wiremock-jre8-standalone-2.25.1.jar:na] 10:29:40 at com.github.tomakehurst.wiremock.WireMockServer.start(WireMockServer.java:146) ~[wiremock-jre8-standalone-2.25.1.jar:na] 10:29:40 ... 44 common frames omitted 10:29:40 Caused by: java.io.IOException: Failed to bind to /0.0.0.0:12193 10:29:40 at wiremock.org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:346) ~[wiremock-jre8-standalone-2.25.1.jar:na] [...] 10:29:40 at com.github.tomakehurst.wiremock.jetty9.JettyHttpServer.start(JettyHttpServer.java:182) ~[wiremock-jre8-standalone-2.25.1.jar:na] 10:29:40 ... 45 common frames omitted 10:29:40 Caused by: java.net.BindException: Address already in use 10:29:40 at java.base/sun.nio.ch.Net.bind0(Native Method) ~[na:na] 10:29:40 at java.base/sun.nio.ch.Net.bind(Net.java:461) ~[na:na] 10:29:40 at java.base/sun.nio.ch.Net.bind(Net.java:453) ~[na:na] 10:29:40 at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:227) ~[na:na] 10:29:40 at java.base/sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:80) ~[na:na] 10:29:40 at wiremock.org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:342) ~[wiremock-jre8-standalone-2.25.1.jar:na] 10:29:40 ... 52 common frames omitted 10:29:40 10:29:40 [ERROR] [1;31mTests [0;1mrun: [0;1m2[m, Failures: 0, [1;31mErrors: [0;1;31m1[m, Skipped: 0, Time elapsed: 15.925 s[1;31m <<< FAILURE! 10:29:40 [ERROR] our.test.Class Time elapsed: 1.843 s <<< ERROR! 10:29:40 com.github.tomakehurst.wiremock.common.FatalStartupException: java.lang.RuntimeException: java.io.IOException: Failed to bind to /0.0.0.0:12193 10:29:40 Caused by: java.lang.RuntimeException: java.io.IOException: Failed to bind to /0.0.0.0:12193 10:29:40 Caused by: java.io.IOException: Failed to bind to /0.0.0.0:12193 10:29:40 Caused by: java.net.BindException: Address already in use
我还为Spring
WireMockConfiguration
启用了DEBUG日志记录,而且很有趣,然后构建成功。它确实提到“在下一个测试中重置映射以重新启动它们。当在随机端口上运行的新服务器重用相同上下文时,这是必要的”。
这使我认为这可能是某种竞争状况,但我不能说我完全掌握了整体设置。
任何指针都会有所帮助。
我们有一个Spring Boot 2.2.0.RELEASE应用程序,正在使用WireMock与JUnit 5测试类进行测试。该测试在本地运行良好,但是在我们的Jenkins上,测试失败,并显示“地址已在使用中” ...