As we move towards a complex eco-system of modularised services, the concept of Contract testing becomes more and more important. At the same time there’s no single solution for all in the market, thus the choice of contract testing strategy becomes key if you really want to reap the benefits.
At the core, Contract Testing means to agree to a contract (api specs in our case) and then ensure it is adhered to while doing the continuous development
When we develop APIs we might follow different styles to write/maintain them, mainly around who’s initiating the contract design. Three key personas who might come in picture can be —
- Consumer — One whose intention is to consume the API.
- Provider — One who develops the API.
- API Designer — One who designs the API and gives to
Corresponding to these there’s a Contract Testing style
- Consumer Driven Contract Testing — Where consumer writes the contract asks provider to implement and validate their implementation against the contract.
- Provider Driven Contract Testing — Where provider writes the contract and consumer tests their implementation against it.
- Design First Contract Testing — Where API Designer creates a contract and both Consumer and Provider test their implementation against it.
One of the most popular out of these is the Consumer Driven Contract Testing but there might be use cases when it’s not wise to go with it.
This articles is focussed on one such alternate which is
Design First Contract Testing. This contract testing style is quite relevant for the Teams who do core API development which is agnostic of consumers and need special design skills. In such Teams one would need an API design tool to finalise the API requirements and brainstorm on it (I will refer SwaggerHub for my examples).
Before moving forward lets compare PACT based Consumer Driven Contract Testing to Swagger Hub base Design First Contract Testing and see what changes for us.
If we notice the key differences, in Design First Contract Testing —
- API designer pushes contracts whereas in PACT Consumer pushes them.
- SwaggerHub (or any API design tool) works like a Broker being a contract store (api spec store) which is the single source of truth in the entire chain.
- Producer/Provider pulls the API spec at runtime and validates them against their implementation. This is quite similar to PACT where Provider pulls the contract at runtime from Broker and checks implementation against it.
- Consumer interacts with the mock generated against the API specs from Swagger Hub, and validate their consumption code with it. This is also similar the PACT where consumer validates their consumption code against the in-memory mock-server generated at runtime.
SwaggerHub provides the mock server out of the box — See here to explore more
Now let’s see how to implement all of these parts. I am using Java SpringBoot for this but you can follow along in the tech of your choice.
We’ll not focus of SwaggerHub here
Step 1 — Design API (API Designer)
Start Designing your API in SwaggerHub. SwaggerHub gives you an easy interface to design the APIs and share the documentation with others to refer to.
Step 2 — Implement and Validate API Specs (Provider)
Let’s create a simple endpoint say /products which gives the list of products available in the system
Say the API Designer designed it like this in SwaggerHub —
Say our controller is written like at Provider end —
The provider can now add below test to validate it against SwaggerHub. Before that we’ll need below maven dependency added.
In the above test you’ll point SWAGGER_HUB_PRODUCTS_API_SPECS_URL to API spec url from SwaggerHub. For testing purpose, I have downloaded the specs and serving them from local.
You can see the working code in my GitHub link.
This test will break in either of the cases when API specs introduces a breaking change or provider implementation doesn’t align with the API Specs.
Step 3— Validate API (Consumer)
Like we discussed before, SwaggerHub provides the mock-endpoint for your specifications out of the box. See here for details.
The consumer tests will be nothing but a copy of integration tests pointing to the SwaggerHub mock endpoint. We may call these “ConsumerContractTests”.
If any breaking change happens in the API specs then these tests will start failing. Also, if any breaking change happens in the way consumer consumes the API then again these tests will break.
Hope this will help you in making a better choice of Contract Testing for your project.