In part 1, we looked at what contract testing is and the gap it can cover in an automation strategy. In part 2, we’re going to look at Pact, which is the most widely used contract testing technology and how its framework implements contract testing.
Pact is referred to as a consumer driven framework, which means the consumer is in control of creating the contract and the contract only contains anything that the consumer actually uses.
Pact is no way replaces any communication between a consumer and a provider, in fact it encourages more communication. Consumer driven does not mean consumer controlled. We’ll examine this more when we see about putting pact in to a CI system, but the main point for now is that the consumer is driving the creation of the pact and leading the discussions as they will benefit the most from the pact being in place. It will give them assurances that the provider they rely on will not break their own functionality when it changes.
The Pact framework
I’ve attempted to sum up the pact process using this simple diagram:
On the consumer side, the pact framework works by running a mock server where you can add “interactions”. These interactions are mock endpoints which are the endpoints the consumer would be hitting on the provider. The framework has utilities where you set the mock up so that given a particular state and input then as a consumer you are expecting the following output.
This forms the “contract” and when the pact framework mock is hit, the framework automatically produces a JSON file which represents this contract.
An example of a simple pact is shown below (I’ve had to blank out any sensitive data to the project I’ve taken this from):
This pact is shown within the Pact Broker, which is a utility I’ll go in to in a later pact but for now I’ve used as it shows the JSON in a nice format.
The first part describes the interaction in human readable form – given a state, upon receiving the below request, then the provider will respond with the below response.
It then describes both the request and the response in simple terms.
- Request -> The REST method, the endpoint path to hit on the provider and any headers and body that are in the request are shown
- Response -> The details here form the checks the provider will perform when it runs this pact and generally consist of a status, one or more headers and a body, but all of these are optional
The provider uses the pact framework to perform the following actions at build time:
- Download or retrieve pacts when it is the provider
- For each pact:
- Run itself
- Hit the endpoint in the request part of the pact with details described in the pact
- Check the actual response matches the checks as described in the pact
- Send result (optional)
The key on the provider side is that the pact is checked by hitting the actual endpoint and not a mock, so if the endpoint code is changed then the pact might fail. I say might as the pact only covers the parts of the endpoint that the consumer is using. If the consumer doesn’t use it, it won’t be covered in the pact. I’ll explain this concept further in later parts.
Pact has an excellent website at https://docs.pact.io/ which fully explains the concepts above. I would recommend taking a look if you think pact can help you.
In part 3, I’ll look in detail at the consumer side with code examples for how you would write the consumer side.