Wiremock: The first test passed But the second test failed when working with spring boot

Created on 20 Mar 2018  Â·  4Comments  Â·  Source: tomakehurst/wiremock

  • wiremock version 2.12.0
  • spring boot test version 1.5.4

this is code

@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(classes = FaceApiTest.Application.class,
        properties = { "face.api.key=api_key",
                "face.api.secret=api_secret",
                "url.face++=http://localhost:9000", "feign.hystrix.enabled=true" },
        webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class FaceApiTest {

    @Autowired
    private FacePlusApi facePlusApi;
    @Rule
    public WireMockRule mockServer = new WireMockRule(9000);
    @Value("${face.api.key}")
    private String apiKey;
    @Value("${face.api.secret}")
    private String apiSecret;

    @After
    public void clean() {
        mockServer.resetAll();
    }

    @Test
    public void testOcrIdCard() {
        Single<OcrIdCardRes> ocrIdCardResSingle = facePlusApi.ocrIdCard(
                "http://s1.wacdn.com");
        TestSubscriber<OcrIdCardRes> subscriber = new TestSubscriber<>();
        ocrIdCardResSingle.subscribe(subscriber);
        subscriber.awaitTerminalEvent();
        subscriber.assertValueCount(1);
        subscriber.assertCompleted();
    }

    @Test
    public void testOcrIdCard2() {
        facePlusApi.ocrIdCard("xx").toBlocking().value();
    }

    @EnableFeignClients(clients = FacePlusApi.class)
    @Configuration
    @EnableAutoConfiguration(
            exclude = { RedAlertAutoConfiguration.class })
    static class Application {

    }
}

this is errormessage

Caused by: java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:210)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at feign.Client$Default.convertResponse(Client.java:152)
    at feign.Client$Default.execute(Client.java:74)
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:97)
    ... 31 more

Most helpful comment

I really need to get round to writing an article about this.

The problem is that the Spring Boot runner starts and stops its servlet container once per class. If you use the WireMock rule as you have it starts and stops once per test method. This means that the pooled connections in the Spring app are rendered invalid between test cases.

You have three options to fix this:
1) Switch to the Spring team's WireMock integration: http://cloud.spring.io/spring-cloud-static/spring-cloud-contract/1.1.2.RELEASE/#_spring_cloud_contract_wiremock
2) Switch to using @ClassRule so that WireMock starts and stops per test class.
3) Configure your Spring HTTP client to detect and discard dead pooled connections. An advantage of this option is that your app will be more resilient to failovers in the production system, as many load balancers/reverse proxies/floating IPs will exhibit similar behaviour.

All 4 comments

image

    @Test
    public void test6() throws InterruptedException {
        Single<OcrIdCardRes> single = facePlusApi.ocrIdCard("xxxxx");
        single.toBlocking().value();
    }

I wonder why

Connections have been closed by the server when the second test accesses the service
@tomakehurst can you help me? thank you

I really need to get round to writing an article about this.

The problem is that the Spring Boot runner starts and stops its servlet container once per class. If you use the WireMock rule as you have it starts and stops once per test method. This means that the pooled connections in the Spring app are rendered invalid between test cases.

You have three options to fix this:
1) Switch to the Spring team's WireMock integration: http://cloud.spring.io/spring-cloud-static/spring-cloud-contract/1.1.2.RELEASE/#_spring_cloud_contract_wiremock
2) Switch to using @ClassRule so that WireMock starts and stops per test class.
3) Configure your Spring HTTP client to detect and discard dead pooled connections. An advantage of this option is that your app will be more resilient to failovers in the production system, as many load balancers/reverse proxies/floating IPs will exhibit similar behaviour.

I'm stupid I should have thought

Was this page helpful?
0 / 5 - 0 ratings