Search code examples
javaspring-bootmockingspring-boot-testwiremock

WireMock On Spring Boot Test With External Https Host


In my application, I have external third party API requests. I want to test my application with mocking this API requests.

My Service Class:

String API_URL = "https://external.com/v1/%s";
public Result executeRequest(String apiVersion, String subUrl, HttpMethod httpMethod)
{
    try
    {
        HttpRequestBase httpRequest;
        String url = String.format(API_URL, subUrl);
        if (httpMethod.equals(HttpMethod.GET))
        {
            httpRequest = new HttpGet(url);
        }
        else if (httpMethod.equals(HttpMethod.POST))
        {
            httpRequest = new HttpPost(url);
            ((HttpPost) httpRequest).setEntity(new StringEntity(requestBody, "UTF-8"));
        }
        ...
        headers.forEach(httpRequest::setHeader);
        HttpResponse response = httpClient.execute(httpRequest);
    }
    catch (IOException e)
    {
        logger.error("IO Error: {}", e.getMessage());
        return handleExceptions(e);
    }
}

To sum up for service class, requests can be get, post, delete, put. And this requests will be processed with headers or body parts. Then will be handled as http request.

My test class:

@SpringBootTest
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
public class ServiceTest
{

    private static final String API_URL = "https://external.com/v1";

    @Autowired
    private Service service;

    @Autowired
    protected Gson gson;

    @Rule
    public WireMockRule wireMockRule = new WireMockRule();

    @Test
    public void getResult_successfully()
    {
        Result result = new Result();
        wireMockRule.stubFor(get(urlPathMatching("/subUrl"))
                .willReturn(aResponse()
                        .proxiedFrom(API_URL)
                        .withStatus(200)
                        .withHeader("Content-Type", "application/json")
                        .withBody(gson.toJson(result))));

        Result returnResult = service.executeRequest("/subUrl", GET);

        assertThat(returnResult).isEqualTo(result);
    }
}

When I implement it like above, mocking doesn't work. Any suggestion?

Note: I hope code snippets will be enough to understand the code in overall.


Solution

  • I solved it like;

    1. Describe test api-url and port. Because Wiremock creates embedded localhost server.

    So in applicaition-properties:

    application-test.properties: 
      - service.url: http://localhost:8484
    application-prod.properties: 
      - service.url: https://external.com/v1
    

    Then my test class:

    @ClassRule
    public static WireMockRule wireMockRule = new WireMockRule(8484);
    
    @Test
    public void getResult_successfully()
    {
        Result result = new Result();
        wireMockRule.stubFor(get(urlPathMatching("/subUrl"))
                .willReturn(aResponse()
                        .proxiedFrom(API_URL)
                        .withStatus(200)
                        .withHeader("Content-Type", "application/json")
                        .withBody(gson.toJson(result))));
    
        Result returnResult = service.executeRequest("/subUrl", GET);
    
        assertThat(returnResult).isEqualTo(result);
    }