---
# The name of your project
title: Spring Cloud Contract

badges:

  # Specify your project's twitter handle, if any. Delete if none.
  twitter: SpringCloudOSS

  # Customize your project's badges. Delete any entries that do not apply.
  custom:
    - name: Source (GitHub)
      url:  https://github.com/spring-cloud/spring-cloud-contract
      icon: github

    - name: StackOverflow
      url:  http://stackoverflow.com/questions/tagged/spring-cloud
      icon: stackoverflow

---
<!DOCTYPE HTML>
<html lang="en-US">

<!-- Specify the parent of this project (or delete if none) to influence the rendering of the breadcrumb -->
{% capture parent_link %}
[Spring Cloud]({{ site.projects_site_url }}/spring-cloud)
{% endcapture %}


{% capture billboard_description %}

Spring Cloud Contract is an umbrella project holding solutions that help users in successfully implementing the [Consumer Driven Contracts](http://martinfowler.com/articles/consumerDrivenContracts.html) approach. Currently
Spring Cloud Contract consists of the Spring Cloud Contract Verifier project.

Spring Cloud Contract Verifier is a tool that enables Consumer Driven Contract (CDC) development of JVM-based applications. It is shipped with Contract Definition Language (DSL) written in Groovy or YAML. Contract definitions are used to produce following resources:

* by default JSON stub definitions to be used by [WireMock](http://wiremock.org) (HTTP Server Stub) when doing integration testing on the client code (client tests). Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier.

* Messaging routes if you’re using one. We’re integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to.

* Acceptance tests (by default in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (server tests). Full test is generated by Spring Cloud Contract Verifier.

Spring Cloud Contract Verifier moves TDD to the level of software architecture.

To see how Spring Cloud Contract supports other languages just check out this [blog post](https://spring.io/blog/2018/02/13/spring-cloud-contract-in-a-polyglot-world).

{% endcapture %}

{% capture main_content %}

## Features

When trying to test an application that communicates with other services then we could do one of two things:

* deploy all microservices and perform end to end tests

* mock other microservices in unit / integration tests

Both have their advantages but also a lot of disadvantages. Let’s focus on the latter.

### Deploy all microservices and perform end to end tests

Advantages:

* simulates production

* tests real communication between services

Disadvantages:

* to test one microservice we would have to deploy 6 microservices, a couple of databases etc.

* the environment where the tests would be conducted would be locked for a single suite of tests (i.e. nobody else would be able to run the tests in the meantime).

* long to run

* very late feedback

* extremely hard to debug

### Mock other microservices in unit / integration tests

Advantages:

* very fast feedback

* no infrastructure requirements

Disadvantages:

* the implementor of the service creates stubs thus they might have nothing to do with the reality

* you can go to production with passing tests and failing production

To solve the aforementioned issues Spring Cloud Contract Verifier with Stub Runner were created. Their main idea is to give you very fast feedback, without the need to set up the whole world of microservices.

Spring Cloud Contract Verifier features:

* ensure that HTTP / Messaging stubs (used when developing the client) are doing exactly what actual server-side implementation will do

* promote acceptance test driven development method and Microservices architectural style

* to provide a way to publish changes in contracts that are immediately visible on both sides of the communication

* to generate boilerplate test code used on the server side

<span id="quick-start"></span>

## Quick Start

<script type="text/javascript">{% include custom.js %}</script>
{% include download_widget.md %}

[For a very detailed step by step guide check out the docs](https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_step_by_step_guide_to_cdc). Below you can find a simplified verstion.

### Server / Producer side

On the server (HTTP) / producer (Messaging) side add the Spring Cloud Contract Verifier Maven / Gradle plugin. Let us assume that our project's group id is `com.example` and artifact id is `http-server`.

The base class for the tests passed in the configuration could look like this (we're assuming that we're using [Rest Assured](http://rest-assured.io/) and we want to do CDC for
a `FraudDetectionController` that you're writing)

```java
package com.example;

// imports

public class MvcTest {

  @Before
  public void setup() {
    RestAssuredMockMvc.standaloneSetup(new FraudDetectionController());
  }

}
```

In the `src/test/resources/contracts` add a Contract definition. For example named `shouldMarkClientAsFraud.groovy`

```groovy
org.springframework.cloud.contract.spec.Contract.make {
  request {
    method 'PUT'
    url '/fraudcheck'
    body("""
    {
      "clientId":"1234567890",
      "loanAmount":99999
    }
    """)
    headers {
      header('Content-Type', 'application/vnd.fraud.v1+json')
    }
  }
response {
  status 200
  body("""
  {
    "fraudCheckStatus": "FRAUD",
    "rejectionReason": "Amount too high"
  }
  """)
  headers {
    header('Content-Type': 'application/vnd.fraud.v1+json')
  }
 }
}
```

If you have to add a plugin that will generate tests and stubs for you.

Maven

```xml
<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-contract-maven-plugin</artifactId>
				<version>${spring-cloud-contract.version}</version>
				<extensions>true</extensions>
				<configuration>
					<baseClassForTests>com.example.MvcTest</baseClassForTests>
				</configuration>
			</plugin>
		</plugins>
	</build>
```

Gradle

```groovy
buildscript {
    repositories {
      mavenCentral()
    }
    dependencies {
      classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootPluginVersion}"
      classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${springCloudContractVersion}"
    }
}

apply plugin: 'spring-boot'
apply plugin: 'spring-cloud-contract'

dependencyManagement {
    imports {
      mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${springCloudDependencies}"
    }
}

dependencies {
    testCompile "org.springframework.cloud:spring-cloud-starter-contract-verifier"
}

contracts {
	baseClassForTests = 'com.example.MvcTest'
}
```

Once you try to build your application from your contracts tests will be generated in the output folder under `/generated-test-sources/contracts`.

```java
package org.springframework.cloud.contract.verifier.tests;

// imports

public class ContractVerifierTest extends MvcTest {

  @Test
  public void validate_shouldMarkClientAsFraud() throws Exception {
    // given:
      MockMvcRequestSpecification request = given()
          .header("Content-Type", "application/vnd.fraud.v1+json")
          .body("{\"clientId\":\"1234567890\",\"loanAmount\":99999}");

    // when:
      ResponseOptions response = given().spec(request)
          .put("/fraudcheck");

    // then:
      assertThat(response.statusCode()).isEqualTo(200);
      assertThat(response.header("Content-Type")).isEqualTo("application/vnd.fraud.v1+json");
    // and:
      DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
      assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD");
      assertThatJson(parsedJson).field("rejectionReason").isEqualTo("Amount too high");
  }
}

```

Once you make them pass and re-run the build and installation of your artifacts then Spring Cloud Contract Verifier will convert the contracts into an HTTP server stub definitions. Currently we're supporting [WireMock](http://wiremock.org). The stub will be present in the output folder under `stubs/mappings/` and will look like this:

```json
{
  "uuid" : "6c509a40-18f3-498c-a19c-c9f8b56957de",
  "request" : {
    "url" : "/fraudcheck",
    "method" : "PUT",
    "headers" : {
      "Content-Type" : {
        "equalTo" : "application/vnd.fraud.v1+json"
      }
    },
    "bodyPatterns" : [ {
      "matchesJsonPath" : "$[?(@.loanAmount == 99999)]"
    }, {
      "matchesJsonPath" : "$[?(@.clientId == '1234567890')]"
    } ]
  },
  "response" : {
    "status" : 200,
    "body" : "{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}",
    "headers" : {
      "Content-Type" : "application/vnd.fraud.v1+json"
    }
  }
}
```

The idea behind CDC (Consumer Driven Contracts) is to share the contract between the sides of the communication. Gradle and Maven plugins help you with that by generating a jar with stubs and contract definitions with a `stubs` classifier. Just upload it to some central repository where others can reuse it for their integration tests.

### Client / Consumer side

On the client (HTTP) / consumer (Messaging) side it's enough to provide a dependency to a proper Spring Cloud Contract Stub Runner implementation. In this case since our example consists of HTTP communication with WireMock as the HTTP Server Stub. We will pick the following dependencies:

Maven

```xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>${spring-cloud-dependencies.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>
```

Gradle

```groovy
buildscript {
    repositories {
      mavenCentral()
    }
    dependencies {
      classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootPluginVersion}"
    }
}

apply plugin: 'spring-boot'

dependencyManagement {
    imports {
      mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${springCloudDependencies}"
    }
}

dependencies {
    testCompile "org.springframework.cloud:spring-cloud-starter-contract-stub-runner"
}
```

The last step is to setup Stub Runner in your tests to automatically download the required stubs. To achieve that
you have to pass the `@AutoConfigureStubRunner` annotation. That annotation has a bunch of properties that you can
set. If you don't like such an approach you can set those values in your test properties too.

For Spring Cloud Contract 1.2.x

```java
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureStubRunner(ids = {"com.example:http-server:+:stubs:8080"}, workOffline = true)
public class LoanApplicationServiceTests {
```

For Spring Cloud Contract starting from 2.0.x

```java
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureStubRunner(ids = {"com.example:http-server:+:stubs:8080"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class LoanApplicationServiceTests {
```

That way an artifact with group id `com.example`, artifact id `http-server`, in `latest` version, with `stubs` classifier will be registered at port `8080`. Since the `workOffline` flag was passed then the stubs will not be downloaded from a remote repository - it will be searched for in the local Maven repo. Once your test context got booted up, executing the following code will not lead to a 404 because the Spring Cloud Contract Stub Runner will automatically start a WireMock server inside your test and feed it with the stubs generated from the server side.

```java
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Content-Type", "application/vnd.fraud.v1+json");
String response = restTemplate.exchange("http://localhost:8080/fraudcheck", HttpMethod.PUT,
            new HttpEntity<>("{\"clientId\":\"1234567890\",\"loanAmount\":99999}", httpHeaders),
            String.class);
assertThat(response).isEqualTo("{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}");
```

{% endcapture %}

{% capture related_resources %}

### Sample Projects

* [Spring Cloud Contract workshops](http://cloud-samples.spring.io/spring-cloud-contract-samples/workshops.html)
* [Producer with HTTP and Messaging contracts](https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer)
* [Consumer of HTTP requests and messages](https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer)
* [Repo with contracts](https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/beer_contracts)
* [Producer using repo with contracts](https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_with_external_contracts)
* [Producer using RestDocs and contracts](https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_with_restdocs)
* [Consumer of RestDocs based stubs](https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_with_restdocs)

{% endcapture %}


{% include project_page.html %}
</html>
