Previously, I took provider and consumer applications and built a full CI/CD workflow, interacting with the Pact Broker.

Next on the list is to talk through contract testing best practices, introducing Provider States. But first, an addendum to the previous post. The changes to perform provider verification using the Pact Broker need to be ported back for when a developer wants to perform provider verification locally. Although there's only a need to do this in one way, in my first post, I demonstrated two solutions supported on the JVM.

In this brief post, I'll cover the changes I needed to interact with the remote Pact Broker.

First off, I deleted the Pact file I copied from the consumer side. Pacts will be retrieved instead from the Broker.

📖 Click here for a fully-worked example of the code in this blog post

Docker-Compose

Rather than hard-coding the Pact Broker Url and authentication token into a file that's committed to source-control, I defined a .env file within the repository, but added it to the project's .gitignore. This file is a simple key-value pairing of properties:

PACT_BROKER_BASE_URL=https://url-to-pact-broker
PACT_BROKER_TOKEN=this-should-be-a-token

.env files are read automatically during docker-compose up and are then available as environment variables.

Now, I need to run the pact-cli image, passing in the broker url, token and the consumer tag to use. Similar to in CI, I chose master to pull in the latest mainline consumer pact:

version: "3"
services:
  app:
    image: pact-provider:latest
    ports:
      - "8081:8081"
  pact:
    image: pactfoundation/pact-cli:latest
    depends_on:
      - app
    links:
      - app
    volumes:
      - ./src/test/resources/pacts:/tmp/pacts
    command: >
      verify
      --consumer-version-tag master
      --provider pact-provider
      --provider_base_url http://app:8081
      --provider-states-setup-url http://app:8081/provider-states
      --pact-broker-base-url ${PACT_BROKER_BASE_URL}
      --broker-token ${PACT_BROKER_TOKEN}
      --wait 10

JUnit

The alternative approach, using JUnit5 test templates, needs a change too. Rather than specifying a @PactFolder, I switch over to @PactBroker. Configuration options can be passed directly to this annotation, I don't want to hard-code any values containing secrets.

package co.uk.samhogy.pact.provider;

import au.com.dius.pact.provider.junitsupport.loader.PactBroker;
// Other imports

@Provider("pact-provider")
@PactBroker()
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ProviderVerificationTests {
  // Nothing changed in here  
}

Instead, the Pact library will look for the following system properties and drive its configuration from there:

  • pactbroker.scheme
  • pactbroker.host
  • pactbroker.port
  • pactbroker.auth.token
  • pactbroker.consumerversionselectors.tags

So, I can pass these in as options when running a Maven build:

./mvnw clean install \
  -Dpactbroker.scheme="https" \
  -Dpactbroker.host="<broker-host>" \
  -Dport="443" \
  -Dpactbroker.auth.token="<token>" \
  -Dpactbroker.consumerversionselectors.tags="master"

The options here are similar to the docker-compose version. It uses the auth token and pulls contracts from consumers with the tag master.