19

I am using wiremock to mock github api to do some testing of my service. The service calls github api. For the tests I am setting endpoint property to

github.api.endpoint=http://localhost:8087

This host and port are the same as wiremock server @AutoConfigureWireMock(port = 8087) so I can test different scenarios like : malformed response, timeouts etc.

How can I make this port dynamic to avoid case when it is already used by system ? Is there a way to get wiremock port in tests and reassign endpoint property ?

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 8087)
@TestPropertySource(properties ={"github.api.endpoint=http://localhost:8087"}) 
public class GithubRepositoryServiceTestWithWireMockServer {

@Value("${github.api.client.timeout.milis}")
private int githubClientTimeout;

@Autowired
private GithubRepositoryService service;

@Test
public void getRepositoryDetails() {
    GithubRepositoryDetails expected = new GithubRepositoryDetails("niemar/xf-test", null,
            "https://github.com/niemar/xf-test.git", 1, "2016-06-12T18:46:24Z");
    stubFor(get(urlEqualTo("/repos/niemar/xf-test"))
            .willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("/okResponse.json")));

    GithubRepositoryDetails repositoryDetails = service.getRepositoryDetails("niemar", "xf-test");

    Assert.assertEquals(expected, repositoryDetails);
}

@Test
public void testTimeout() {
    GithubRepositoryDetails expected = new GithubRepositoryDetails("niemar/xf-test", null,
            "https://github.com/niemar/xf-test.git", 1, "2016-06-12T18:46:24Z");
    stubFor(get(urlEqualTo("/repos/niemar/xf-test"))
            .willReturn(aResponse()
                    .withHeader("Content-Type", "application/json")
                    .withBodyFile("/okResponse.json")
                    .withFixedDelay(githubClientTimeout * 3)));

    boolean wasExceptionThrown = false;
    try {
        GithubRepositoryDetails repositoryDetails = service.getRepositoryDetails("niemar", "xf-test");
    } catch (GithubRepositoryNotFound e) {
        wasExceptionThrown = true;
    }

    Assert.assertTrue(wasExceptionThrown);
}

5 Answers 5

29

You have to set the WireMock port to 0 so that it chooses a random port and then use a reference to this port (wiremock.server.port) as part of the endpoint property.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
@TestPropertySource(properties = {
    "github.api.endpoint=http://localhost:${wiremock.server.port}"
}) 
public class GithubRepositoryServiceTestWithWireMockServer {
    ....
}

See also Spring Cloud Contract WireMock.

2
  • 1
    Do you know if this property should work for Micronaut as well? I'm getting this error: Caused by: io.micronaut.context.exceptions.ConfigurationException: Could not resolve placeholder ${wiremock.server.port}
    – dcalap
    Commented May 16, 2023 at 10:37
  • 1
    I finally figured out you need to tell WireMockSpring to actually use this port if you are overriding the Options bean: ` @Configuration static class Config { @Bean Options options( @Value("${wiremock.server.port}") int wireMockPort) { ... return WireMockSpring.options() .port(wireMockPort) `
    – AmanicA
    Commented Mar 22 at 23:46
14

I know this is a bit old post but still there is a documented way to have these ports dynamically. Read more here: Getting started. Just scroll down a bit to 'Random port numbers'. From the documentation there:

What you need to do is to define a Rule like so

@Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());  

And then access them via

int port = wireMockRule.port();
int httpsPort = wireMockRule.httpsPort();
10

One more way, you can use dynamic port without conflict is

import org.springframework.util.SocketUtils;

int WIREMOCK_PORT = SocketUtils.findAvailableTcpPort();

public WireMockRule wireMockServer = new WireMockRule(WIREMOCK_PORT);

if you want to access it from properties file, then we have wiremock.server.portprovided by Wiremock

"github.api.endpoint=http://localhost:${wiremock.server.port}"
1
  • Do you know if this property should work for Micronaut as well? I'm getting this error: Caused by: io.micronaut.context.exceptions.ConfigurationException: Could not resolve placeholder ${wiremock.server.port}
    – dcalap
    Commented May 16, 2023 at 10:38
3

I am not aware of @AutoConfigureWireMock but if you are manually starting wiremock and setting up mocks, while starting spring you can setup a random port number utilizing spring random. A sample will look like this

in your wiremock class

@Component
public class wiremock {
    @Value("${randomportnumber}")
    private int wiremockPort;

   public void startWiremockServer() {
        WireMock.configureFor("localhost", wiremockPort);
        wireMockServer = new com.github.tomakehurst.wiremock.WireMockServer(wireMockConfig().port(wiremockPort).extensions
                (MockedResponseHandler.class));
        wireMockServer.start();
   }

}

In your test class

//however you want to configure spring
public class wiremock {

    @Value("${github.api.endpoint}")
    private String wiremockHostUrl;

   //use the above url to get stubbed responses.
}

in your application.properties file

randomportnumber=${random.int[1,9999]}
github.api.endpoint=http://localhost:${randomportnumber}
5
  • I will check it
    – niemar
    Commented Mar 20, 2018 at 15:38
  • I will check on weekend
    – niemar
    Commented Mar 22, 2018 at 7:35
  • Not really. Even if I remove wiremock annotation and run stub as WireMockClassRule, the mock server always starts before spring properties are read. Thank for your help.
    – niemar
    Commented Apr 1, 2018 at 18:31
  • @niemar I have updated my answer, aren't you starting wiremock server as I stated above? Commented Apr 2, 2018 at 2:03
  • I like the use of ${random.int[1,9999]} as an alternative to @AutoConfigureWireMock, I used the equivalent ${random.port} with a Micronaut application. Commented Nov 22, 2021 at 11:58
0

If you are using .NET/C#, you can just start the WireMock server with empty arguments like so:

var myMockServer = WireMockServer.Start();

and then get the port number if you need it like this:

int portNumber = myMockServer.Port();

Not the answer you're looking for? Browse other questions tagged or ask your own question.