Setting mock ports for multiple providers in pact-jvm

752 Views Asked by At

I am trying to learn the pact framework by rewriting some of our wiremock tests that test our application written in java and springboot. I have provided a simplified example of where we end up getting stuck:

Consumertest.java

@ExtendWith(PactConsumerTestExt.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class ContractConsumerTests {

    @Autowired
    private MockMvc mockMvc;

    @Pact(provider = "provider1", consumer = "my_consumer")
    public V4Pact provider1Pact(PactBuilder builder) {
        ...
    }

    @Pact(provider = "provider2", consumer = "my_consumer")
    public V4Pact provider2Pact(PactBuilder builder) {
        ...
    }

    @Test
    @PactTestFor(pactMethods = {"provider1Pact", "provider2Pact"})
    public void testMultipleProvider(@ForProvider("provider1") MockServer provider1Mock, @ForProvider("provider2") MockServer provider2Mock) throws Exception {
        System.out.println(provider1Mock.getPort()); //random port != 1000
        System.out.println(provider2Mock.getPort()); //random port != 2000

        //Calling this controller requires fetching data from provider1 and provider2 to compute the result
        //application is configured to go to provider1 on localhost:1000 and provider 2 on localhost:2000
        mockMvc.perform(get("/my/url")
                        .param("foo", "abc")
                        .param("bar", "123"))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedcontent"));
    }
}

Application.yml

application:
  client:
    provider1:
      url: http://localhost:1000/
    provider2:
      url: http://localhost:2000/

Previously we would have a single wiremock instance running on a set port (1000), and the application config would point to that port for both providers. However we can not do that now, since the resulting contract would then contain requests for both providers. If we were to give the contract to provider1 it could not satisfy the requests from provider2 and vica-versa.

A similar question was asked 2 years ago: How to define multiple providers using @PactTestFor, which answer was to split the test. This probably wont work for us for various reasons. But more importantly there is now support for multi provider tests: https://docs.pact.io/implementation_guides/jvm/consumer/junit5#using-multiple-providers-in-a-test-425

Now, when you have but one provider in your test, you can specify the port for the mock with:

@PactTestFor(providerName = "provider1", port="1000")

This will then match the port configured in the application and all is fine. However, since we are using multiple providers, using 'port=1000' will now lead to an 'address already in use' exception. Which makes sense, when both mockservers try to start on port 1000.

Ommitting the port will default to a random port which will resolve the exception, but the application is configured to call a static port, which will never match the random port. And thus will always fail.

That then leads to the questions:
How can we use whatever random mock port was chosen in our application configuration?
or
How can we set the port per instance of MockServer to match the port in our config?

1

There are 1 best solutions below

1
On