Verify Pact Contract And Continuous Deployment With Pact CLI

By Sruthy

By Sruthy

Sruthy, with her 10+ years of experience, is a dynamic professional who seamlessly blends her creative soul with technical prowess. With a Technical Degree in Graphics Design and Communications and a Bachelor’s Degree in Electronics and Communication, she brings a unique combination of artistic flair…

Learn about our editorial policies.
Updated March 9, 2024

In this tutorial, we will look at how to set up a provider test, manage state, verify the contract, and deploy using Pact Broker CLI:

Consumer-Driven Contract Testing is driven by the consumer and the provider pulls the scenarios (interactions) down from the Pact Broker and runs them against their local environment or In-Memory Server. We are going to use PactNet to verify our contracts, the other popular back-end languages that are supported (incl. PHP, Java, Python).

A typical scenario where the provider comes in is when the Front-End team is interacting with the provider API.

Once the provider has been verified, you will want to communicate the status back to the consumer on whether they can deploy their version of the application containing the new Pact contract or not.

=> Check ALL Contract Testing Tutorials Here

PactNet _ Verifying Pact Contract And Continuous Deployment with Can I Deploy CLI

The Pact Broker Client offers a CLI tool that allows you to check the status of your contract within the Pact Broker. This is the final step to the contract testing flow, which allows you to deploy your microservice to production with confidence.

Writing The Provider Test

The scenario for the tutorial will be:

Password strength, the consumer interaction is creating a new password for the user and the API provider returns 200 for valid passwords or 400 for invalid.

The provider can now deploy their API with confidence, knowing that they are not going to break their consumers. Contract Testing also allows the provider to run some of their typical integration scenarios before deploying to the integration environment and thereby saving time & resources.

In this tutorial, we will look at how to set up a provider test, manage state (data setup), and verify the contract from the Pact Broker.

Referring to the scenario above, the consumer interaction describes an error scenario where an invalid password “p&ssw0rd1” is submitted, and the API responds with a 400 HTTP code along with an error message: “Please enter a valid password, including at least 1 uppercase character”.

Installing Pact Provider Test Dependencies

Installing PactNet relies on only one test core package in order to run the tests, and in this tutorial, we are using NUnit.

NUnit is the test framework that will provide the structure of the tests and assertions. PactNet comes with different implementations based on your OS, therefore you will need to install the relevant nuget packages (supports: Windows, Mac, Linux).

dotnet add package NUnit 
dotnet add package PactNet
dotnet add package PactNet.OSX

`.csproj` should look as shown below:

<?xml version=”1.0″ encoding=”utf-8″?>
<Project Sdk=”Microsoft.NET.Sdk”>
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include=”Microsoft.NET.Test.Sdk” Version=”16.4.0″ />
<PackageReference Include=”NUnit” Version=”3.10.1″ />
<PackageReference Include=”NUnit3TestAdapter” Version=”3.10.0″ />
<PackageReference Include=”PactNet” Version=”2.0.17″ />
<PackageReference Include=”PactNet.OSX” Version=”2.0.17″ />
</ItemGroup>
</Project>

Create a new file `ProviderTests.cs` and import the following:

using NUnit.Framework;
using PactNet;

Set Up Pact Provider Configuration

Initialize Pact within the constructor and provide configuration options pointing to the Pact Broker:

private readonly string _serviceUri;

private readonly string _pactUri;

private readonly IPactVerifier _pactVerifier;

public ProviderTests() {
            _serviceUri = "http://localhost:5001";
            _pactUri = "http://pact-broker.dius.com/pacts/";
            var pactVerifierConfig = new PactVerifierConfig {
                PublishVerificationResults = true,
                ProviderVersion = "1.0.0"
            };
            _pactVerifier = new PactVerifier(pactVerifierConfig);
}

_serviceUri: Local instance of the provider API.
_pactDirectory: Pact Broker url, Consumer and Provider contracts.
PublishVerificationResults: Pact Broker updates the status of the verification result (this should be set to true within your CI pipeline, therefore an environment variable should be used).
ProviderVersion: API version, Pact suggests using git hash for this value.

Set Up Provider State

Pact state is a statement that the consumer provides within the consumer tests, and this often reflects the data that is required before the test can be run. In this example, in order to change a password for the user, we need to have an existing user.

Therefore within our provider tests, we need to set up the state before the test starts. PactNet uses middleware to set up the state before the Pact verification occurs, see the Owin Server example.

Verify Contract

This is where you make a request to the local server. Within the test, the Pact pulls the contract from the Pact Broker and makes the request to the localhost along with the details from the contract, E.g. Headers and Query Params. Then Pact verifies the request made to the API server and returns the expected body.

Verify Expectations on Provider

[image source]

The test passes the Pact Broker URI to pull down the contract and verify it. In order to access the Pact Broker, you will need to get the Username and Password or the API key.

[Test]
public void ensureReactAppHonoursPasswordContract() {
    _pactVerifier
    .ServiceProvider("Password", _serviceUri)
    .HonoursPactWith("ReactApp")
    .PactUri($"{_pactUri}/provider/Password/consumer/ReactApp/latest", new PactUriOptions("API_KEY"))
    .Verify();
 }

Once you call `Verify()` the request will be sent and the assertions will be checked.

Run Provider Tests

To execute the tests, you just need to open a new terminal and execute:

dotnet test

If there is an error, you can see this on the console or within the Pact Broker.

Run Provider Tests

Can I Deploy My Application With Pact CLI

For example, a new version of the token API is to be released and that adds a higher level of security to the token by requiring multi-factor authentication.

The consumer updates the app to support multi-factor by requiring the user to receive a code via text message, and they update the contract with the token API service. Push the new contract to the Pact Broker, MFA-V1.

Then the provider makes the changes to the API to support multi-factor by adding a mandatory field that accepts multi-factor code. Then the provider pulls down the contract from the Pact Broker and runs its contract tests against MFA-V1.

The status is updated within the Pact Broker to say that the provider has successfully verified the contract. At this point, the consumer can use the can-i-deploy CLI to confirm that their contract has been verified and they can deploy to production knowing that everything works in line with their implementation.

Installing Pact Broker Client

Standalone Pact Broker Client

Pact Broker Client is available as a ruby standalone executable that can be downloaded. Once you have downloaded the standalone package, navigate to the `bin` folder and now you can run the version command to check if it is ready to be used.

The output should be something like “1.26.0”

./pact-broker version

Docker Pact Broker Client

In order to get the full value from the can-i-deploy CLI, you will want to run the command within your continuous integration (CI) pipeline. Pact Broker Client has a docker image that allows you to run the Pact Broker Client commands within a docker container that can fit nicely into your CI infrastructure.

I’m using Github Actions to demo this functionality but this can obviously be used in other CI environments.

name: Can I Deploy

on:
 release:
   types: [created]

 can-i-deploy:
   runs-on: ubuntu-latest
   container: pactfoundation/pact-cli
   steps:
     - name: Pacticipant React
       env:
         PACT_BROKER_BASE_URL: https://lewisprescott.pact.dius.com.au/
         PACT_BROKER_USERNAME: ${{ secrets.PACT_BROKER_USERNAME }}
         PACT_BROKER_PASSWORD: ${{ secrets.PACT_BROKER_PASSWORD }}
         broker can-i-deploy --pacticipant React --version 1.0.0

Github actions use triggers to run workflows, here we are using the release trigger so when a release is created from Github then the following steps will be executed. The can-i-deploy steps use the docker container: pactfoundation/pact-cli to run the CLI command that we have provided.

broker can-i-deploy --pacticipant React --version 1.0.0

The Pact Broker settings are passed as environment variables, including the Pact Broker URL. Utilizing Github Secrets we can store the username and password or API key within the secrets store and not expose them within Git.

When the Github Action is triggered the environment variables will be set and the command runs within the docker container. The status of the workflow can be found in the Actions section of the Github repo.

Tagging Release With Pact Version

In order to check whether you can deploy to a specific environment or even production, you need to tag the specific environment with a release version so that the Pact Broker knows which version to use within the can-i-deploy.

./pact-broker create-version-tag --pacticipant ReactApp --version 1.0.0 --tag Test

pacticipant: Name of the consumer or provider (Pacticipant is a great name)
version: Version of pacticipant being deployed.
tag: Environment in this example (E.g. Integration or Test)

Once you have tagged the Pacticipant you know which environment has which version. This will ensure backward compatibility and if the provider wants to check then they can release a new version that won’t break the existing consumers.

Also, the consumer can check if they can release the new app and confirm if it still complies with the existing provider version.

Can I Deploy Verification Status

can-i-deploy CLI communicates with the Pact Broker and returns the verification status. This completes the contract testing cycle.

  1. Consumer publishes contract
  2. Provider verifies contract
  3. Deployment: Consumer / Provider confirms tests have been executed
./pact-broker can-i-deploy --pacticipant ReactApp --version 1.0.0 --to
 Test --broker-base-url https://lewisprescott.pact.dius.com.au --broker-token *******

pacticipant: Name of the consumer or provider
version: Version of pacticipant being deployed
tag: Environment in this example (E.g. Integration or Test)
broker-base-url: Pact Broker url
broker-token: API Key (located within settings > API tokens in Pactflow), if your broker has basic authentication, then you will also need to pass.
broker-username: Pact Broker username
broker-password: Pact Broker password

Run the command, and you should receive a successful response.

However, if the verification has failed then you will receive an error message as shown below:

cli error

Conclusion

In this tutorial, we have learned how to set up the provider tests using PactNet, and saw how provider state could be set up using middleware. Now you have verified the consumer contract, and this may raise more questions about the way the consumer is interacting with the API.

This is such a powerful communication tool within microservices as usually so many assumptions are made and these decisions are made much earlier in the process. Ultimately it would be great if Solution Architects could be at the forefront of creating consumer contracts alongside the teams and have Pact built in from the start.

The Pact Broker CLI adds the finishing touch, by tagging your environments and verifying the status the full flow is automated and can be built into your CI pipeline. Each step may live in different CI pipelines but all come together before you release your software to production.

This offers the missing piece of the puzzle when it comes to developing microservices where you rely on heavy and brittle End-to-End tests that run on your integration environments. From my experience, these tests are duplicated across different teams, increasing their maintenance and running costs.

We have now completed all the tutorials on Contract Testing, each step takes you one step closer to achieving continuous deployment.

In achieving this within your organization you will have:

  • Improved communication between the silos within your microservices.
  • Reduced time to release (not having to rely on deploying to integration environments).
  • Increased understanding of consumer behaviors and interactions.
  • Enhanced visibility of the integration points of the microservice architecture.

This is the final tutorial on Contract Testing, we hope you are persuaded on Pact and what it can offer your organization, if you still need some convincing then check out the convince me docs.

=> Visit Here To See The Contract Testing Training Series For All

Was this helpful?

Thanks for your feedback!

Leave a Comment