Rizwan Shakoor
Rizwan Shakoor

Reputation: 73

java.net.SocketTimeoutException in integration test in Java while using Wiremock using Spring Boot with Junit

I'm using wiremock in to mock external operator response in integration test:

@ClassRule
public static WireMockClassRule zainWireMockStatic = new WireMockClassRule(9900);

and getting this exception

requesting to java.net.SocketTimeoutException: connect timed out timed out

This is my wiremock

 private static void wireMockZainUnSubscriptionRequest() {
        zainWireMockStatic.stubFor(get(urlPathMatching("/api/unsubscribe")).willReturn(
                aResponse().withStatus(200).withHeader("Content-Type", "application/json")
                        .withBody(FileUtils.readFileFromClasspath(
                                "data/mocks/zain_unsubscribe_success_response.json"))));

    }

and this is my test

    @Test
    public void unsubscribeUserWithSuccessResponse() {
        wireMockZainUnSubscriptionRequest();
        given().body(FileUtils.readFileFromClasspath("data/message/unsubscribe_request.json"))
                .contentType(ContentType.JSON).post(UNSUBSCRIBE_API).then().statusCode(200)
                .body("user_id", equalTo(USER_ID));

    }

Upvotes: 2

Views: 6743

Answers (2)

Roger Frauca
Roger Frauca

Reputation: 11

Hi I had the same problem, and I followed the advice of bernyfox on the github and solve the problem.

My problem was with the http client it reports the SocketTimeout. The proposed solution is to tell the httpclient the connection will be close with an extension.

I made this one:

public class ConnectionCloseExtension extends ResponseTransformer {

    @Override
    public ResponseDefinition transform(Request request, ResponseDefinition response, FileSource files) {
        HttpHeaders headersWithClose;
        HttpHeader closeHeader = new HttpHeader("Connection", "Close");
        if(response.getHeaders()!=null){
            headersWithClose = HttpHeaders.copyOf(response.getHeaders())
                    .plus(closeHeader);
        }else{
            headersWithClose = new HttpHeaders(closeHeader);
        }
        response.setHeaders(headersWithClose);
        return response;
    }

    @Override
    public String name() {
        return "ConnectionCloseExtension";
    } }

and to apply it:

@Rule
public WireMockRule wireMockServer = new WireMockRule(wireMockConfig()
        .extensions(new ConnectionCloseExtension()));

Upvotes: 1

user7515307
user7515307

Reputation:

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.

Upvotes: 1

Related Questions