It's a pact!
This article is about Consumer-Driven Contract Testing which as its quite a mouthful, can also be called pact testing. A few months ago, our team at Target started the process of combining several monolith apps into one unified flow composed of multiple microservices.
Now we have a few microservices that talk to each other. We are building everything all at the same time (thank you, Event Storming for the bounded contexts!) and find that we are both consumers and providers of our services. We want to be able to make frequent releases but don't want to break any canonical/contracts of consuming services that are already in Production. And we want to do this without running expensive end to end tests. Simply because, by the time we get to the end to end testing, the story is already in "Done" state.
Enter consumer-driven contract testing.
The term Consumer Driven Contracts was made popular by Martin Fowler and is now a strategy in the toolkit of microservice developers. The idea behind consumer-driven contract testing is simple. The consumer of an API creates a Pact which is basically the contract between itself and the provider it is invoking.
Say a UserProvider Service exposes an API to fetch the details of a user. Doing a GET on /user/7914 would return a JSON response that looks like this
As a consumer of this API, I want to validate the following contract as this is how I envision consuming the UserProvider API:
Now that this contract is defined, as the UserProviderService I might decide to make a change to the contract. As an example, the provider may decide to make the "hobbies" field nullable. If the provider validated the above consumer contract, it would break the build. since the consumer expects hobbies to be a String value.
The Pact.io framework allows consumers to easily create tests that codify the contract in a manner similar to the above and generate a Pact file. This pact file is then shared with the Provider who uses this during the development process to validate code changes.
This additional step requires communication and trust between the Provider and Consumer API teams. Having a pact verification step in the CI build for the Provider can break the Provider build. It requires the Provider to trust the Consumer to write the test correctly. It also requires the Consumer to trust the Provider that the pact will be respected.
Nothing replaces actual conversation between Provider and Consumer. Pact just makes it easier to codify those conversations.
Pact.io is supported in Ruby/Java/Scala/Groovy and can be run as JUnit/Springboot/Spock tests executed via Gradle/Maven. It is a very active open source project and has an easy learning curve. Consumer-Driven contract testing is a valuable tool for microservices testing, and this article only scratches the surface of the framework's capabilities.
Nice Sunita Venkatachalam !
Director of Engineering - Engineering Leader with Product, People and Customer accountabilities
7 年Nicely written... Explained in very simple terms...??