This workshop is aimed at demonstrating core features and benefits of contract testing with Pact.
Whilst contract testing can be applied retrospectively to systems, we will follow the consumer driven contracts approach in this workshop - where a new consumer and provider are created in parallel to evolve a service over time, especially where there is some uncertainty with what is to be built.
This workshop should take from 1 to 2 hours, depending on how deep you want to go into each topic.
Workshop outline:
- step 1: create consumer: Create our consumer before the Provider API even exists
- step 2: unit test: Write a unit test for our consumer
- step 3: pact test: Write a Pact test for our consumer
- step 4: pact verification: Verify the consumer pact with the Provider API
- step 5: fix consumer: Fix the consumer's bad assumptions about the Provider
- step 6: pact test: Write a pact test for
404
(missing User) in consumer - step 7: provider states: Update API to handle
404
case - step 8: pact test: Write a pact test for the
401
case - step 9: pact test: Update API to handle
401
case - step 10: request filters: Fix the provider to support the
401
case - step 11: pact broker: Implement a broker workflow for integration with CI/CD
- step 12: simulate CI: Run a simulation of a CI pipeline to understand how pact interacts with CI
NOTE: Each step is tied to, and must be run within, a git branch, allowing you to progress through each stage incrementally. For example, to move to step 2 run the following: git checkout step2
If running this as a team workshop format, you may want to take a look through the learning objectives.
There are two components in scope for our workshop.
- Product Catalog website. It provides an interface to query the Product service for product information.
- Product Service (Provider). Provides useful things about products, such as listing all products and getting the details of an individual product.
We need to first create an HTTP client to make the calls to our provider service:
The Consumer has implemented the product service client which has the following:
GET /products
- Retrieve all productsGET /products/{id}
- Retrieve a single product by ID
The diagram below highlights the interaction for retrieving a product with ID 10:
You can see the client interface we created in consumer/src/api.js
:
export class API {
constructor(url) {
if (url === undefined || url === "") {
url = process.env.REACT_APP_API_BASE_URL;
}
if (url.endsWith("/")) {
url = url.substr(0, url.length - 1);
}
this.url = url;
}
withPath(path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
return `${this.url}${path}`;
}
async getAllProducts() {
return axios.get(this.withPath("/products")).then((r) => r.data);
}
async getProduct(id) {
return axios.get(this.withPath("/products/" + id)).then((r) => r.data);
}
}
After forking or cloning the repository, we may want to install the dependencies npm install
.
We can run the client with npm start --prefix consumer
- it should fail with the error below, because the Provider is not running.
Move on to step 2