We live in a world ruled by distributed systems and each of these systems has its very own caracteristics. Following a Service Oriented Architecture and sometimes using a specific flavor such as microservices we must guarantee that the comunication across all these services remain consistent.
That is why the API contract is so important, the way each service will receive and return data must be well defined, documented and managed in a way that changes will not result in failures on multiples clients. Thats why we use tools such as swagger to api documentation and versioning contracts to prevent breaking changes to have huge impacts on clients already consuming our contracts, but how we can guarantee that this contract are not beeing broken by any daily changes on our service?
There are some options such as integration and e2e tests, that will guarantee the behavior and communication of our system but they often are very slow and demand a lot of effort to be written and maintained. Thats not a reason to not use them or remove completely from our pipeline, but may not be the correct tool for our problem, we must have a fast and cheap way to validate our contract and prevent unwanted breaking changes.
Thats why something called Contract Test is needed. Its a methodology for ensuring that your contract stays compatible and will fail when any breaking change is introduced. They must be lighweitgh in order to be runned alongside unit tests and give the developer an early and fast feedback on the impact of the introduced code. To achieve that mocking the implementation and not relying on external resources is the way go to prevent flaky tests.
Spring Cloud Contract bring a lot of these functionalites into the java ecosystem, so lets take a look on how to implement that. First of all we need a simple API, the example bellow will receive a number and return a result if it is EVEN or ODD
Then we will need to add SpringCloudContract to our classpath to be able to declare our contract test in groovy.
And we’ll need to configure spring-cloud-contract-maven-plugin with the name of our base test class
Then the contract can be written in a declarative form and a test will be generated from this file.
In order to mock the service implementation and only keep the contract beeing tested we must written a default class that will be extended on the generated test.
The generated test will look like this
This way, on your build pipeline not only the unit tests will run but also these generated contract tests always validating the introduced code. There are a lot of other functionalities on Spring Cloud Contract that can help your development, for example it will generate a “stubbed jar” using wiremock, that will respond accordingly to the groovy declarative tests, in a way that consumers can import this jar an use it for testing their calls to our API without the real call. So on the consumer side a test can be written like this
Spring Cloud Contract is a great tool to help our contract tests but it is not the only tool available, when leaving the spring framework and diving into java servlet for example, jersey can be used to solve this problems and other tooling can be used to do the same thing, but the most important is that by implementing contract test we can guarantee that our communication with several clients will remain compatible no matter what change is done on our implementation.