Pact Consumer

This extension ensures Pact consumer libraries works well with Quarkus applications, including with continuous testing. It is based on version 4.3.17 of the Pact JVM JUnit 5 library.

Installation

To use this extension, add the io.quarkiverse:quarkus-pact-consumer extension first to your build file. Choose a 1.x version for Quarkus 3, and a 0.x version for Quarkus 2.

For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse</groupId>
    <artifactId>quarkus-pact-consumer</artifactId>
    <version>0.2.1</version>
    <scope>provided</scope>
</dependency>

Note the provided scope, rather than test or default. This is needed for the tests to pass in continuous testing mode.

Example usage

Use Pact as you normally would. Remember that your consumer tests should be testing your application’s code, not the behaviour of the Pact-provided mock.

For example, a simple consumer test for REST endpoints would look like this:

(1)
@ExtendWith(PactConsumerTestExt.class)
@PactTestFor(providerName = "farm", port = "8085")
@PactDirectory("target/pacts")
@QuarkusTest (2)
public class ConsumerTest {

    (3)
    @Inject
    Knitter knitter;

    @Pact(provider = "farm", consumer = "knitter")
    public V4Pact createPact(PactDslWithProvider builder) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");

        return builder.given("test GET") (4)
                .uponReceiving("GET REQUEST")
                .path("/alpaca")
                .method("GET")
                .willRespondWith()
                .status(200)
                .headers(headers)
                .body(" {\n" + (5)
                        "      \"colour\": \"black\",\n" +
                        "          \"name\": \"floppy\"\n" +
                        "        }")
                .toPact(V4Pact.class);
    }

    @Test
    public void testConsumption() { (6)
        String knitted = knitter.knit("irrelevant"); (7)
        assertEquals("a nice striped sweater", knitted);
    }
}
1 Add @Consumer annotations to the class, along with metadata about who the consumer is, and what provider is being used.
2 Needed to enable dependency injection of the rest client.
3 The consumer under test.
4 We use the Pact DSL to define what the provider should return, given the request.
5 Here we define our mock, which is also our expectations for the provider. There is no need to verify these in this test; instead, the provider test will verify them.
6 This test is realistic (in a simplified way) of how a consumer test might look.
7 We have hardcoded the mock response, so the colour parameter we pass in is irrelevant (for this particular test) It tests how the consumer under test uses what the mock passes back, not the mock itself.

Extension Configuration Reference

For the moment, Pact needs to be configured by the normal Pact system properties.

Known limitations

  • If continuous testing is being used, the dependency scope cannot be test. The provided scope is a good alternative.

  • @TestProfile does not work in dev mode (GitHub issue)

  • A harmless java.lang.NoClassDefFoundError: org/apache/hc/client5/http/fluent/Request message will be produced if Pact tracking is enabled (GitHub issue)

Samples and resources