Open In App

Spring Cloud Contract

Last Updated : 29 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Spring Cloud Contract is a framework for writing Consumer Driven Contracts (CDC) in Spring applications. It enables teams to define contracts between microservices, ensuring proper communication. Spring Cloud Contract allows developers to create and manage contracts for RESTful APIs, ensuring consistency and reliability across distributed systems. Automating contract testing helps improve efficiency and reduce integration issues between projects.

Spring Cloud Contract is an umbrella service that includes tools to help customers incorporate customer-friendly contracting options. Currently, the Spring Cloud contract contains the Spring Cloud Contract Verifier Project.

Implementation of Spring Cloud Contract

Step 1: Add Dependencies

We may include the Spring Cloud Contract Verifier dependency and plugin in our build file, as shown in the following example:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>

Step 2: Specify the Base Test Class

The following example from pom.xml demonstrates how to provide the basic test class.

XML
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-contract-maven-plugin</artifactId>
            <version>3.1.2.RELEASE</version>
            <extensions>true</extensions>
            <configuration>
                <baseClassForTests>com.example.contractTest.BaseTestClass</baseClassForTests>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>


Step 3: Include a Basic Class in the Package

This test class creates a mock environment and a Spring context for testing a Spring Boot application. It sets up the required configuration for the tests to function properly and initializes a controller for testing.

Java
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import com.example.controllers.EvenOddController;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@DirtiesContext
@AutoConfigureMessageVerifier
public class YourNewTestClass {

    @Autowired
    private EvenOddController evenOddController;

    @Before
    public void setup() {
        StandaloneMockMvcBuilder standaloneMockMvcBuilder 
          = MockMvcBuilders.standaloneSetup(evenOddController);
        RestAssuredMockMvc.standaloneSetup(standaloneMockMvcBuilder);
    }
}
  • The @SpringBootTest annotation is utilized to define the loading and configuration parameters for the Spring ApplicationContext. Here, it offers a simulated web environment along with loading the entire application context.
  • @DirtiesContext annotation suggests that the test’s Spring ApplicationContext has to be closed and deleted following test execution since it is unclean.

Step 4: Configure the Consumer – Client Side

To preserve the contract, the consumer side of our CDC will consume stubs created by the producer side via HTTP interaction; hence, any modifications on the producer side will break the contract.

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class NewMathController {

    @Autowired
    private RestTemplate newRestTemplate;

    @GetMapping("/calculate")
    public String checkOddAndEven(@RequestParam("number") Integer number) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");

        ResponseEntity<String> responseEntity = newRestTemplate.exchange(
          "http://localhost:8090/validate/prime-number?number=" + number,
          HttpMethod.GET,
          new HttpEntity<>(httpHeaders),
          String.class);

        return responseEntity.getBody();
    }
}

Step 5: Available stubs information

For microservices-based architectures to be reliable and correct, integration testing is essential. It is critical to verify that services in these distributed systems communicate appropriately and follow established contracts. Next set up stub runner, which will notify consumers about the available stubs in local Maven repository:

Java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@AutoConfigureStubRunner(
  stubsMode = StubRunnerProperties.StubsMode.LOCAL,
  ids = "org.geeksforgeeks.spring.cloud:spring-cloud-contract-producer:+:stubs:8090")
public class NewMathControllerIntegrationTest {

    @Autowired
    private MockMvc newMockMvc;

    @Test
    public void given_WhenPassEvenNumberInQueryParam_ThenReturnEven()
      throws Exception {
 
        newMockMvc.perform(MockMvcRequestBuilders.get("/calculate?number=2")
          .contentType(MediaType.APPLICATION_JSON))
          .andExpect(status().isOk())
          .andExpect(content().string("Even"));
    }
}
  • @SpringBootTest indicates how to load and set up the Spring ApplicationContext using this annotation. Here, it loads the entire application context and offers a test-ready fake web environment.
  • @AutoConfigureStubRunner sets up a Stub Runner automatically to use stubs from a local or remote repository. It is set up to retrieve stubs from a local repository in this instance.
  • newMockMvc.execute() is used where you can begin a simulated HTTP request. It is employed to provide a number=2 query parameter along with an HTTP GET request to the /calculate endpoint.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads