Addendum: Pact Provider Verification
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
.