Enterprise Java

Consumer Driven Testing with Pact & Spring Boot

Recently a colleague of mine stumbled across Pact.io,  Our current application had grown to over 50 services and we we’re starting to have some integration test failures and a brittle dev / acceptance test environment. So we decided to have a look at ways to try help with this.

I started out by reading: https://docs.pact.io/faq/convinceme.html

Then watching: https://www.youtube.com/watch?v=-6x6XBDf9sQ&feature=youtu.be

Those 2 resources convinced me to give it a shot.

So I set out and created a quick set of Spring boot apps, the GitHub repo here, to test out the concepts and get everything working.

To highlight some important bits from the demo.


As Pact is a consumer driven test framework. This is where you define a unit test, that test mocks the http server response and you assert against that.

Once the test is successful it creates a pact json file in the /pacts directory.

public class TestProvider {
    public PactProviderRule provider = new PactProviderRule("test_provider", "localhost", 8081, this);

    @Pact(state = "default", provider = "test_provider", consumer = "test_consumer")
    public PactFragment createFragment(PactDslWithProvider builder) {
        Map<String, String> headers = new HashMap<>();
        headers.put("content-type", "application/json");

        return builder
                .uponReceiving("Test User Service")
                .body("{" +
                        "  \"userName\": \"Bob\",\n" +
                        "  \"userId\": \"1\",\n" +
                        "  \"firstName\": null,\n" +
                        "  \"lastName\": null,\n" +
                        "  \"email\": null,\n" +
                        "  \"groups\": null\n" +

    public void runTest() throws IOException {
        final RestTemplate call = new RestTemplate();
         final User expectedResponse = new User();
        final User forEntity = call.getForObject(provider.getConfig().url() + "/user/1", User.class);
        assertThat(forEntity, sameBeanAs(expectedResponse));


So after the “mock” test is run and the pact file has been created. You need to include a maven plugin …pact… that is then used to publish the content of the pacts/ folder to the pact broker… which is defined in the pom as below.

	<!-- https://mvnrepository.com/artifact/au.com.dius/pact-jvm-consumer-junit_2.11 -->



This uses the JUnit integration from Pact.io to download the pacts from the broker and then run against an running service.

Since this already uses a @RunWith annotation, I could not use the spring boot runner. So to get around that as a before class step, I start the Spring boot application, the pacts then gets run against that running instance… and the boot application gets stopped again after the tests. Depending on your use case I guess it would also be an option to do this with @Before so you get a new service instance started before each pack, but that would slow down the execution tremendously.

The @State annotation, allows for clients to define a specific state, which the producer can the use to setup additional data / conditions required for the test to run.

Once the pacts have executed against the service there are reports generated in the target folder.

@Provider("test_provider" )
@PactBroker(host = "localhost", port = "80")
@VerificationReports({"console", "markdown"})
public class TestPacts {
    private static ConfigurableApplicationContext application;
    public final Target target = new HttpTarget(8080);
    public static void startSpring(){
        application = SpringApplication.run(ProviderServiceApplication.class);

    public void toDefaultState() {
        System.out.println("Now service in default state");

    public void toExtraState() {
        System.out.println("Now service in extra state");

    public static void kill(){

Setting up the Pact Broker

1. Grab the public images from Docker Hub.

docker pull dius/pact_broker
docker pull postgres

2. Then setup the Postgres DB

docker run --name pactbroker-db -e POSTGRES_PASSWORD=ThePostgresPassword -e POSTGRES_USER=admin -d postgres
docker run -it --link pactbroker-db:postgres --rm postgres psql -h postgres -U admin
CREATE USER pactbrokeruser WITH PASSWORD 'TheUserPassword';
CREATE DATABASE pactbroker WITH OWNER pactbrokeruser;
GRANT ALL PRIVILEGES ON DATABASE pactbroker TO pactbrokeruser;

3. Once the DB is up, run the actual Broker:

docker run --name pactbroker --link pactbroker-db:postgres -e PACT_BROKER_DATABASE_USERNAME=pactbrokeruser -e PACT_BROKER_DATABASE_PASSWORD=TheUserPassword -e PACT_BROKER_DATABASE_HOST=postgres -e PACT_BROKER_DATABASE_NAME=pactbroker -d -p 80:80 dius/pact_broker

Extra References:

Get the example project

Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Newest Most Voted
Inline Feedbacks
View all comments
Datta Sai
Datta Sai
3 years ago

I have a query that for doing the PACT Consumer driven contract testing we have to STUB the API in our local machine and then test it

Back to top button