Learn how to use Spring Cloud Contract to create and verify consumer-driven contracts between microservices. Implement contract testing between UserService
(producer) and OrderService
(consumer).
-
Generate a new Spring Boot project for
UserService
.- Visit https://start.spring.io/.
- Configure the project:
- Spring Boot Version:
3.1.4
- Group Id:
com.microservices
- Artifact Id:
user-service
- Dependencies:
- Spring Web
- Spring Boot Actuator
- Spring Cloud Contract Verifier (Version:
4.0.2
)
- Spring Boot Version:
- Extract the zip file into a folder named
UserService
.
-
Import the
UserService
project into your IDE. -
Create a REST controller for
UserService
.- Add
UserController.java
:package com.microservices.userservice; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/users/{id}") public User getUserById(@PathVariable String id) { return new User(id, "John Doe"); } } class User { private String id; private String name; public User(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
- Add
-
Add a contract file.
- Create
src/test/resources/contracts/user-get-contract.groovy
:Contract.make { description "Should return user details for a given ID" request { method GET() urlPath('/users/1') } response { status 200 body([ id: '1', name: 'John Doe' ]) headers { contentType(applicationJson()) } } }
- Create
-
Enable Spring Cloud Contract Verifier.
- Add the following Maven plugin to
pom.xml
:<build> <plugins> <plugin> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-maven-plugin</artifactId> <version>4.0.2</version> <extensions>true</extensions> <configuration> <baseClassForTests>com.microservices.userservice.BaseContractTest</baseClassForTests> </configuration> </plugin> </plugins> </build>
- Add the following Maven plugin to
-
Create a base test class for the contract.
- Add
BaseContractTest.java
:package com.microservices.userservice; import io.restassured.module.mockmvc.RestAssuredMockMvc; import org.junit.jupiter.api.BeforeEach; public abstract class BaseContractTest { @BeforeEach void setUp() { RestAssuredMockMvc.standaloneSetup(new UserController()); } }
- Add
-
Generate stubs.
- Run:
./mvnw clean install
- Run:
-
Verify the generated stubs.
- Confirm stubs are available under
target/stubs
.
- Confirm stubs are available under
-
Generate a new Spring Boot project for
OrderService
.- Visit https://start.spring.io/.
- Configure the project:
- Artifact Id:
order-service
- Dependencies:
- Spring Web
- Spring Boot Actuator
- Spring Cloud Contract Stub Runner
- Spring WebClient
- Artifact Id:
- Extract the zip file into a folder named
OrderService
.
-
Import the
OrderService
project into your IDE. -
Add stub dependency for
UserService
.- Add to
pom.xml
:<dependency> <groupId>com.microservices</groupId> <artifactId>user-service</artifactId> <version>0.0.1-SNAPSHOT</version> <classifier>stubs</classifier> <scope>test</scope> </dependency>
- Add to
-
Configure Stub Runner.
- Add to
src/test/resources/application.properties
:stubrunner.ids-to-fetch=com.microservices:user-service:+:stubs stubrunner.stubs-mode=LOCAL stubrunner.repository-root=target/stubs
- Add to
-
Create a REST controller in
OrderService
.- Add
OrderController.java
:package com.microservices.orderservice; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; @RestController public class OrderController { @Autowired private WebClient.Builder webClientBuilder; @GetMapping("/orders") public String getOrders() { String user = webClientBuilder.build() .get() .uri("http://localhost:8081/users/1") .retrieve() .bodyToMono(String.class) .block(); return "Orders from OrderService and User: " + user; } }
- Add
-
Run
OrderService
../mvnw spring-boot:run
-
Create a contract test for
OrderService
.- Add
OrderServiceContractTest.java
:package com.microservices.orderservice; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; @SpringBootTest @AutoConfigureStubRunner public class OrderServiceContractTest { @Test public void shouldFetchUserDetails() { String user = WebClient.builder() .baseUrl("http://localhost:8081") .build() .get() .uri("/users/1") .retrieve() .bodyToMono(String.class) .block(); assert user.contains("John Doe"); } }
- Add
-
Run the tests.
./mvnw test
-
Extend the contract.
- Add a new field (e.g.,
email
) to theUser
object and update the contract.
- Add a new field (e.g.,
-
Add a third consumer.
- Create a
ProductService
and implement contract testing withUserService
.
- Create a
-
Publish stubs to a central repository.
- Push generated stubs to an artifact repository like Nexus or Artifactory.