Consumer Driven Contract with Spring Boot
Hi, in this article we will talk about the details of consumer driven development.
The main problem is the conflict between consumer and producer on API interface. When you are developing an API, you have to think about the comfort of your clients. If the changes that you make break the clients, it is completely a joke. In this article, we discuss some of the challenges in consumer & producer services.
Consumer Driven Contact(CDC) ensures the correct contract between Producer and Consumer, in a distributed system or microservices for HTTP based or message based or event based software.
Spring Cloud Contract is an implementation of CDC development of JVM based language. It’s also support for the non-jvm based language. It moves TDD to the level of the software(API) design&architecture. I call it CDC -> Client Driven Development because client(consumer) drives the changes of the API of the producer.
You can find a sample application in this tutorial.
As I mentioned the problem and solution above, you can think why we need this approach. There are some challenges in microservice architecture design while making handshake between consumer and producer. Therefore a change made by the producer is very difficult to test on the consumer side.
When trying to test an application that communicates many other services we could do one of the things without Consumer Driven Contract as below;
- Deploy all microservices with resource and perform end-to-end test.
- Mock other services in tests.
Both approaches have their advantages and disadvantages.
Deploy all microservices;
Pros -> simulates production, test real services, more reliable
Cons -> long to run, hard to debug, many cost(deploy many apps, many resources such as DB, cache etc), very late feedback
Mock other services;
Pros -> very fast feedback, no need to set up the infrastructure
Cons -> not reliable, you can go to prod with passing tests and failing prod
To solve these issues Spring Cloud Contract were created.
I follow these steps while developing a new feature for application;
- Prepare contract.
- Generate a test from a prepared contract.
- Coding with TDD and red-green style.
- After the feature has been completed, you can create stubs(contract) jar.
- Consumer can use created stub jar for integration between api’s.
Firstly we will create a contract with Groovy DSL as below;
We made a sample contract for retrieve account. We have requested ‘api/v1/accounts’ endpoint with ‘accountId’ query param with HTTP get method. And we sent accept header as JSON. Finally, we’ve expected that response status should be ok(200) and response header contentType should be JSON and response body should be equals to JSON response file. Response as follow;
Before generating test class we should configure contract plugin;
You can generate test class from contract and coding with TDD style. You can do it via generateTests maven goal as follow -> mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:2.0.1.RELEASE:generateTests
Generated test placed under the target/generated-test-sources. Generated test;
You can run it as normal JUnit tests. After tests passes you can share your contract with your client&consumer.
When you modify endpoint such as rename URL or add/delete params, you should modify the contract. If you don’t modify, build could not pass.
Spring cloud contract plugin generates stub jar for you. You can deploy it to artifactory or local repo. Spring cloud contract supports different stub modes such as classpath or local m2 repo or remote artifactory. We will use local m2 mode.
Let’s consume stub jar;
With @AutoConfigureStubRunner annotation spring setup wiremock server easily for you. Real producer API should be up on 8090 port. And we create reel HTTP request and assert response data. If any steps fail CI/CD pipeline is not passing. Even in your local environment instead of CI server.
All source code available on github repo.