Search code examples
javaapitestingconsumerpact

Pact: Solving PactMismatchesException


I'm trying to setup a contract test with Pact (so far only Consumer-side). This is what my code looks like:

    @Pact(consumer = "Consumer")
    RequestResponsePact apiIsReachablePact(PactDslWithProvider builder) {
        return builder.given("api is reachable")
                .uponReceiving("load api")
                .method("GET")
                .path("/?format=json")
                .willRespondWith()
                .status(200)
                .headers(headers())
                .body(newJsonBody(object -> {
                    object.stringType("ip", "XYZ");
                }).build())
                .toPact();
    }

    @Test
    @PactTestFor(pactMethod = "apiIsReachablePact")
    public void apiIsReachable() throws IOException {

        //Given
        HttpUriRequest request = new HttpGet("https://api.ipify.org");

        //When
        HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);

        //Then
        assertEquals(httpResponse.getStatusLine().getStatusCode(), HttpStatus.SC_OK);
    }

I tried to make it as simple as possible, but I receive the following error:

au.com.dius.pact.consumer.PactMismatchesException: The following requests were not received:
    method: GET
    path: /?format=json
    query: {}
    headers: {}
    matchers: MatchingRules(rules={})
    generators: Generators(categories={})
    body: MISSING
    ...

Could anyone please help me along here?


Solution

  • Pact doesn't intercept your requests, so this call doesn't actually talk to the Pact mock server, hence why it was not received - it's going to the real API:

            HttpUriRequest request = new HttpGet("https://api.ipify.org");
    

    You don't test against real API in Pact in the consumer test, you mock out the provider and test using the Pact Mock. It will then generate a contract that the provider can then use to verify your expectations:

    It should be:

        @Test
        @PactTestFor(pactMethod = "apiIsReachablePact")
        public void apiIsReachable(MockServer mockServer) throws IOException {
    
            //Given
            HttpUriRequest request = new HttpGet(mockServer.getUrl());
    
            //When
            HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
    
            //Then
            assertEquals(httpResponse.getStatusLine().getStatusCode(), HttpStatus.SC_OK);
        }
    

    See this example and this workshop for more.