[[using]]
= Using Spring Cloud Contract
include::_attributes.adoc[]

This section goes into more detail about how you should use {project-full-name}. It covers topics
such as flows of how to work with {project-full-name}. We also
cover some {project-full-name} best practices.

If you are starting out with {project-full-name}, you should probably read the
<<getting-started.adoc#getting-started, Getting Started>> guide before diving into this
section.

[[flows-provider-nexus]]
== Provider Contract Testing with Stubs in Nexus or Artifactory

You can check the <<getting-started.adoc#getting-started-first-application, Developing Your First Spring Cloud Contract based application>> link to see the provider contract testing with stubs in the Nexus or Artifactory flow.

[[flows-provider-git]]
== Provider Contract Testing with Stubs in Git

In this flow, we perform the provider contract testing (the producer has no knowledge of how consumers use their API). The stubs are uploaded to a separate repository (they are not uploaded to Artifactory or Nexus).

[[prerequisites]]
=== Prerequisites

Before testing provider contracts with stubs in git, you must provide a git repository
that contains all the stubs for each producer. For an example of such a project, see
{samples_code}/contract_git[this samples ] or {samples_code}/contract_git[this sample].
As a result of pushing stubs there, the repository has the following structure:

====
[source,bash,indent=0]
----
$ tree .
└── META-INF
   └── folder.with.group.id.as.its.name
       └── folder-with-artifact-id
           └── folder-with-version
               ├── contractA.groovy
               ├── contractB.yml
               └── contractC.groovy

----
====

You must also provide consumer code that has Spring Cloud Contract Stub Runner set up. For
an example of such a project, see {samples_code}/consumer[this sample] and search for a
`BeerControllerGitTest` test. You must also provide producer code that has Spring Cloud
Contract set up, together with a plugin. For an example of such a project, see
{samples_code}/producer_with_empty_git[this sample].

[[flows-provider-git-flow]]
=== The Flow

The flow looks exactly as the one presented in
<<getting-started.adoc#getting-started-first-application, Developing Your First Spring Cloud Contract based application>>,
but the `Stub Storage` implementation is a git repository.

You can read more about setting up a git repository and setting consumer and producer side
in the <<howto.adoc#how-to-use-git-as-storage,How To page>> of the documentation.

[[flows-provider-git-consumer]]
=== Consumer setup

In order to fetch the stubs from a git repository instead of Nexus or Artifactory, you
need to use the `git` protocol in the URL of the `repositoryRoot` property in Stub Runner.
The following example shows how to set it up:

====
[source,java,indent=0,subs="verbatim,attributes",role="primary"]
.Annotation
----
@AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
		repositoryRoot = "git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git",
		ids = "com.example:artifact-id:0.0.1")
----

[source,java,indent=0,subs="verbatim,attributes",role="secondary"]
.JUnit 4 Rule
----
@Rule
	public StubRunnerRule rule = new StubRunnerRule()
			.downloadStub("com.example","artifact-id", "0.0.1")
			.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
			.stubsMode(StubRunnerProperties.StubsMode.REMOTE);
----

[source,java,indent=0,subs="verbatim,attributes",role="secondary"]
.JUnit 5 Extension
----
@RegisterExtension
	public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension()
			.downloadStub("com.example","artifact-id", "0.0.1")
			.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
			.stubsMode(StubRunnerProperties.StubsMode.REMOTE);
----
====

[[flows-provider-git-producer]]
=== Setting up the Producer

To push the stubs to a git repository instead of Nexus or Artifactory, you need
to use the `git` protocol in the URL of the plugin setup. Also you need to explicitly tell
the plugin to push the stubs at the end of the build process. The following examples show
how to do so in both Maven and Gradle:

====
[source,xml,indent=0,role="primary"]
.Maven
----
<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>${spring-cloud-contract.version}</version>
    <extensions>true</extensions>
    <configuration>
        <!-- Base class mappings etc. -->

        <!-- We want to pick contracts from a Git repository -->
        <contractsRepositoryUrl>git://git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>

        <!-- We reuse the contract dependency section to set up the path
        to the folder that contains the contract definitions. In our case the
        path will be /groupId/artifactId/version/contracts -->
        <contractDependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>${project.artifactId}</artifactId>
            <version>${project.version}</version>
        </contractDependency>

        <!-- The contracts mode can't be classpath -->
        <contractsMode>REMOTE</contractsMode>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <!-- By default we will not push the stubs back to SCM,
                you have to explicitly add it as a goal -->
                <goal>pushStubsToScm</goal>
            </goals>
        </execution>
    </executions>
</plugin>
----

[source,groovy,indent=0,role="secondary"]
.Gradle
----
contracts {
	// We want to pick contracts from a Git repository
	contractDependency {
		stringNotation = "${project.group}:${project.name}:${project.version}"
	}
	/*
	We reuse the contract dependency section to set up the path
	to the folder that contains the contract definitions. In our case the
	path will be /groupId/artifactId/version/contracts
	 */
	contractRepository {
		repositoryUrl = "git://git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git"
	}
	// The mode can't be classpath
	contractsMode = "REMOTE"
	// Base class mappings etc.
}

/*
In this scenario we want to publish stubs to SCM whenever
the `publish` task is run
*/
publish.dependsOn("publishStubsToScm")
----
====

You can read more about setting up a git repository in the
<<howto.adoc#how-to-use-git-as-storage,How To section>> of the documentation.

[[flows-cdc-contracts-producer]]
== Consumer Driven Contracts with Contracts on the Producer Side

See <<getting-started.adoc#getting-started-cdc, Step-by-step Guide to Consumer Driven
Contracts (CDC) with Contracts on the Producer Side>> to see the Consumer Driven Contracts
with contracts on the producer side flow.

[[flows-cdc-contracts-external]]
== Consumer Driven Contracts with Contracts in an External Repository

In this flow, we perform Consumer Driven Contract testing. The contract definitions are
stored in a separate repository.

[[prerequisites]]
=== Prerequisites

To use consumer-driven contracts with the contracts held in an external repository, you need to set up a git repository that:

* Contains all the contract definitions for each producer.
* Can package the contract definitions in a JAR.
* For each contract producer, contains a way (for example, `pom.xml`) to install stubs
locally through the Spring Cloud Contract Plugin (SCC Plugin).

For more information, see the <<howto.adoc#how-to-common-repo-with-contracts, How To section>>,
where we describe how to set up such a repository.
For an example of such a project, see {samples_code}/beer_contracts[this sample].

You also need consumer code that has Spring Cloud Contract Stub Runner set up.
For an example of such a project, see {samples_code}/consumer[this sample].
You also need producer code that has Spring Cloud Contract set up, together with a plugin.
For an example of such a project, see {samples_code}/producer_with_external_contracts[this sample].
The stub storage is Nexus or Artifactory.

At a high level, the flow is as follows:

. The consumer works with the contract definitions from the separate repository.
. Once the consumer's work is done, a branch with working code is created on the consumer
side, and a pull request is made to the separate repository that holds the contract definitions.
. The producer takes over the pull request to the separate repository with contract
definitions and installs the JAR with all contracts locally.
. The producer generates tests from the locally stored JAR and writes the missing
implementation to make the tests pass.
. Once the producer's work is done, the pull request to the repository that holds the
contract definitions is merged.
. After the CI tool builds the repository with the contract definitions and the JAR with
contract definitions gets uploaded to Nexus or Artifactory, the producer can merge its branch.
. Finally, the consumer can switch to working online to fetch stubs of the producer from a
remote location, and the branch can be merged to master.

[[flows-cdc-contracts-external-consumer]]
=== Consumer Flow

The consumer:

. Writes a test that would send a request to the producer.
+
The test fails due to no server being present.
. Clones the repository that holds the contract definitions.
. Sets up the requirements as contracts under the folder, with the consumer name as a subfolder of the producer.
+
For example, for a producer named `producer` and a consumer named `consumer`, the contracts would be stored under `src/main/resources/contracts/producer/consumer/`)
. Once the contracts are defined, installs the producer stubs to local storage, as the following example shows:
+
====
[source,bash,indent=0]
----
$ cd src/main/resource/contracts/producer
$ ./mvnw clean install
----
====
. Sets up Spring Cloud Contract (SCC) Stub Runner in the consumer tests, to:
* Fetch the producer stubs from local storage.
* Work in the stubs-per-consumer mode (this enables consumer driven contracts mode).
+
The SCC Stub Runner:
* Fetches the producer stubs.
* Runs an in-memory HTTP server stub with the producer stubs.
Now your test communicates with the HTTP server stub, and your tests pass.
* Creates a pull request to the repository with contract definitions, with the new contracts for the producer.
* Branches your consumer code, until the producer team has merged their code.

The following UML diagram shows the consumer flow:

[plantuml, flow-overview-consumer-cdc-external-consumer, png]
----
"Consumer"->"Repo\nwith\ncontracts": clone
"Repo\nwith\ncontracts"->"Repo\nwith\ncontracts\nclone": cloned
"Consumer"->"Repo\nwith\ncontracts\nclone": create contract\ndefinitions of\nthe [Producer]
"Repo\nwith\ncontracts\nclone"->"Local storage": install [Producer]\nstubs locally
"Consumer"->"Consumer\nBuild": run tests
"Consumer\nBuild"->"SCC\nStub Runner": Run [Producer] stubs
"SCC\nStub Runner"->"Local storage": fetch [Producer] stubs
"SCC\nStub Runner"->"Producer stub": stub is running
"Consumer\nBuild"->"Producer stub": send a request\nin the tests
"Producer stub"->"Consumer\nBuild": send a response
"Consumer\nBuild"->"Consumer": the tests are passing
"Consumer"->"Repo\nwith\ncontracts\nclone": send a pull request
"Repo\nwith\ncontracts\nclone"->"Repo\nwith\ncontracts": pull request sent
"Consumer"->"Consumer": branch the code
----

[[flows-cdc-contracts-external-producer]]
=== Producer Flow

The producer:

. Takes over the pull request to the repository with contract definitions. You can do it
from the command line, as follows
+
====
[source,bash,indent=0]
----
$ git checkout -b the_branch_with_pull_request master
git pull https://github.com/user_id/project_name.git the_branch_with_pull_request
----
====
. Installs the contract definitions, as follows
+
====
[source,bash,indent=0]
----
$ ./mvnw clean install
----
====
. Sets up the plugin to fetch the contract definitions from a JAR instead of from
`src/test/resources/contracts`, as follows:
+
====
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
----
<plugin>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-maven-plugin</artifactId>
	<version>${spring-cloud-contract.version}</version>
	<extensions>true</extensions>
	<configuration>
		<!-- We want to use the JAR with contracts with the following coordinates -->
		<contractDependency>
			<groupId>com.example</groupId>
			<artifactId>beer-contracts</artifactId>
		</contractDependency>
		<!-- The JAR with contracts should be taken from Maven local -->
		<contractsMode>LOCAL</contractsMode>
		<!-- ... additional configuration -->
	</configuration>
</plugin>
----

[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
.Gradle
----
contracts {
	// We want to use the JAR with contracts with the following coordinates
	// group id `com.example`, artifact id `beer-contracts`, LATEST version and NO classifier
	contractDependency {
		stringNotation = 'com.example:beer-contracts:+:'
	}
	// The JAR with contracts should be taken from Maven local
	contractsMode = "LOCAL"
	// Additional configuration
}
----
====
. Runs the build to generate tests and stubs, as follows:
+
====
[source,bash,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
----
./mvnw clean install
----

[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
.Gradle
----
./gradlew clean build
----
====
. Writes the missing implementation, to make the tests pass.
. Merges the pull request to the repository with contract definitions, as follows:
+
====
[source,bash,indent=0]
----
$ git commit -am "Finished the implementation to make the contract tests pass"
$ git checkout master
$ git merge --no-ff the_branch_with_pull_request
$ git push origin master
----
====
+
The CI system builds the project with the contract definitions and uploads the JAR with
the contract definitions to Nexus or Artifactory.
. Switches to working remotely.
. Sets up the plugin so that the contract definitions are no longer taken from the local
storage but from a remote location, as follows:
+
====
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
----
<plugin>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-maven-plugin</artifactId>
	<version>${spring-cloud-contract.version}</version>
	<extensions>true</extensions>
	<configuration>
		<!-- We want to use the JAR with contracts with the following coordinates -->
		<contractDependency>
			<groupId>com.example</groupId>
			<artifactId>beer-contracts</artifactId>
		</contractDependency>
		<!-- The JAR with contracts should be taken from a remote location -->
		<contractsMode>REMOTE</contractsMode>
		<!-- ... additional configuration -->
	</configuration>
</plugin>
----

[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
.Gradle
----
contracts {
	// We want to use the JAR with contracts with the following coordinates
	// group id `com.example`, artifact id `beer-contracts`, LATEST version and NO classifier
	contractDependency {
		stringNotation = 'com.example:beer-contracts:+:'
	}
	// The JAR with contracts should be taken from a remote location
	contractsMode = "REMOTE"
	// Additional configuration
}
----
====
. Merges the producer code with the new implementation.
. The CI system:
** Builds the project.
** Generates tests, stubs, and the stub JAR.
** Uploads the artifact with the application and the stubs to Nexus or Artifactory.

The following UML diagram shows the producer process:

[plantuml, flow-overview-consumer-cdc-external-producer, png]
----
"Producer"->"Repo\nwith\ncontracts": take over the pull request
"Producer"->"Repo\nwith\ncontracts": install the contract\ndefinitions JAR
"Repo\nwith\ncontracts"->"Local storage": install the\ncontract definitions\nJAR locally
"Local storage"->"Repo\nwith\ncontracts": contract definitions\nJAR installed
"Producer"->"Producer\nBuild": run build
"Producer\nBuild"->"SCC\nPlugin": generate tests,\nstubs\nand stub jar
"SCC\nPlugin"->"Local storage": fetch the contract definitions
"Local storage"->"SCC\nPlugin": contract definitions found
"SCC\nPlugin"->"SCC\nPlugin": generate tests
"Producer\nBuild"->"Producer\nBuild": run the\ngenerated tests
"Producer\nBuild"->"Producer": the tests failed to pass
"Producer"->"Producer": write the missing implementation
"Producer"->"Producer\nBuild": run the build again
"Producer\nBuild"->"Producer\nBuild": fetch the contract definitions\nrun the generated tests
"Producer\nBuild"->"Producer": the tests passed
"Producer"->"Repo\nwith\ncontracts": merge the pull request
"Repo\nwith\ncontracts"->"CI": build and upload the\ncontract definitions artifact
"CI"->"Stub Storage": upload the\ncontract definitions
"Producer"->"Producer": setup the SCC Plugin\nto work remotely
"Producer"->"Producer": merge the code\nwith the implementation
"Producer"->"CI": build and upload\nthe artifacts
"CI"->"Producer\nBuild\non CI": generate tests,\nstubs\nand stub jar
"Producer\nBuild\non CI"->"SCC\nPlugin": generate tests,\nstubs\nand stub jar
"SCC\nPlugin"->"Stub Storage": fetch the contract definitions
"Stub Storage"->"SCC\nPlugin": contract definitions found
"SCC\nPlugin"->"SCC\nPlugin": generate tests
"Producer\nBuild\non CI"->"CI": the build passed
"Producer\nBuild\non CI"->"Stub Storage": upload the application JAR\nand the stubs jar
----

[[flows-cdc-contracts-stubs-git]]
== Consumer-driven Contracts with Contracts on the Producer Side, Pushed to Git

You can read the <<getting-started.adoc#getting-started-cdc, Step-by-step Guide to Consumer Driven Contracts (CDC) with contracts laying on the producer side>> to see the consumer driven contracts with contracts on the producer side flow.

The stub storage implementation is a git repository. We describe its setup in the
<<flows-provider-git>> section.

You can read more about setting up a git repository for the consumer and producer sides in
the <<howto.adoc#how-to-use-git-as-storage,How To section>> of the documentation.

[[flows-provider-non-spring]]
== Provider Contract Testing with Stubs in Artifactory for a non-Spring Application

[[flows-provider-non-spring-flow]]
=== The Flow

You can read <<getting-started.adoc#getting-started-first-application, Developing Your First Spring Cloud Contract-based Application>> to see the flow for provider contract testing with stubs in Nexus or Artifactory.

[[flows-provider-non-spring-consumer]]
=== Setting up the Consumer

For the consumer side, you can use a JUnit rule. That way, you need not start a Spring context. The following listing shows such a rule (in JUnit4 and JUnit 5);

====
[source,java,indent=0,subs="verbatim,attributes",role="primary"]
.JUnit 4 Rule
----
@Rule
	public StubRunnerRule rule = new StubRunnerRule()
			.downloadStub("com.example","artifact-id", "0.0.1")
			.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
			.stubsMode(StubRunnerProperties.StubsMode.REMOTE);
----

[source,java,indent=0,subs="verbatim,attributes",role="secondary"]
.JUnit 5 Extension
----
@RegisterExtension
	public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension()
			.downloadStub("com.example","artifact-id", "0.0.1")
			.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
			.stubsMode(StubRunnerProperties.StubsMode.REMOTE);
----
====

[[flows-provider-non-spring-producer]]
=== Setting up the Producer

By default, the Spring Cloud Contract Plugin uses Rest Assured's `MockMvc` setup for the
generated tests. Since non-Spring applications do not use `MockMvc`, you can change the
`testMode` to `EXPLICIT` to send a real request to an application bound at a specific port.

In this example, we use a framework called https://javalin.io[Javalin] to start a
non-Spring HTTP server.

Assume that we have the following application:

====
[source,java,indent=0]
----
package com.example.demo;

import io.javalin.Javalin;

public class DemoApplication {

	public static void main(String[] args) {
		new DemoApplication().run(7000);
	}

	public Javalin start(int port) {
		return Javalin.create().start(port);
	}

	public Javalin registerGet(Javalin app) {
		return app.get("/", ctx -> ctx.result("Hello World"));
	}

	public Javalin run(int port) {
		return registerGet(start(port));
	}

}
----
====

Given that application, we can set up the plugin to use the `EXPLICIT` mode (that is, to
send out requests to a real port), as follows:

====
[source,xml,indent=0,role="primary"]
.Maven
----
<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.demo.BaseClass</baseClassForTests>
		<!-- This will setup the EXPLICIT mode for the tests -->
		<testMode>EXPLICIT</testMode>
	</configuration>
</plugin>
----

[source,groovy,indent=0,role="secondary"]
.Gradle
----
contracts {
	// This will setup the EXPLICIT mode for the tests
	testMode = "EXPLICIT"
	baseClassForTests = "com.example.demo.BaseClass"
}
----
====

The base class might resemble the following:

====
[source,java,indent=0]
----
import io.javalin.Javalin;
import io.restassured.RestAssured;
import org.junit.After;
import org.junit.Before;
import org.springframework.cloud.test.TestSocketUtils;

public class BaseClass {

	Javalin app;

	@Before
	public void setup() {
		// pick a random port
		int port = TestSocketUtils.findAvailableTcpPort();
		// start the application at a random port
		this.app = start(port);
		// tell Rest Assured where the started application is
		RestAssured.baseURI = "http://localhost:" + port;
	}

	@After
	public void close() {
		// stop the server after each test
		this.app.stop();
	}

	private Javalin start(int port) {
		// reuse the production logic to start a server
		return new DemoApplication().run(port);
	}
}
----
====

With such a setup:

* We have set up the Spring Cloud Contract plugin to use the `EXPLICIT` mode to send real
requests instead of mocked ones.
* We have defined a base class that:
** Starts the HTTP server on a random port for each test.
** Sets Rest Assured to send requests to that port.
** Closes the HTTP server after each test.

[[flows-provider-non-jvm]]
== Provider Contract Testing with Stubs in Artifactory in a Non-JVM World

In this flow, we assume that:

* The API Producer and API Consumer are non-JVM applications.
* The contract definitions are written in YAML.
* The Stub Storage is Artifactory or Nexus.
* Spring Cloud Contract Docker (SCC Docker) and Spring Cloud Contract Stub Runner Docker
(SCC Stub Runner Docker) images are used.

You can read more about how to use Spring Cloud Contract with Docker link:docker-project.html[here].

https://spring.io/blog/2018/02/13/spring-cloud-contract-in-a-polyglot-world[Here], you can
read a blog post about how to use Spring Cloud Contract in a polyglot world.

https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs/[Here], you can find
a sample of a NodeJS application that uses Spring Cloud Contract both as a producer and a
consumer.

[[flows-provider-non-jvm-producer]]
=== Producer Flow

At a high level, the producer:

. Writes contract definitions (for example, in YAML).
. Sets up the build tool to:
.. Start the application with mocked services on a given port.
+
If mocking is not possible, you can set up the infrastructure and define tests in a stateful way.
.. Run the Spring Cloud Contract Docker image and pass the port of a running application as an environment variable.

The SCC Docker image:
* Generates the tests from the attached volume.
* Runs the tests against the running application.

Upon test completion, stubs get uploaded to a stub storage site (such as Artifactory or Git).

The following UML diagram shows the producer flow:

[plantuml, flows-provider-non-jvm-producer, png]
----
"API Producer"->"API Producer": write contract definitions
"API Producer"->"API Producer": (preferable) prepare a way\nto run the app\nwith mocked services
"API Producer"->"API Producer\nbuild": run the build
"API Producer\nbuild"->"API Producer\nrunning app": run the app\non port X\nwith mocked services
"API Producer\nbuild"->"SCC Docker": attach contract definitions\nas a volume
"API Producer\nbuild"->"SCC Docker": set environment variables\ne.g. app running on port X
"API Producer\nbuild"->"SCC Docker": run the contract tests
"SCC Docker"->"SCC Docker\nimage": run the contract tests
"SCC Docker\nimage"->"SCC Docker\nimage": pick the contract definitions\nfrom volume
"SCC Docker\nimage"->"SCC Docker\nimage": generate contract tests
"SCC Docker\nimage"->"SCC Docker\nimage": run the tests\nagainst app running\non port X
"SCC Docker\nimage"->"SCC Docker\nimage": the tests are passing!
"SCC Docker\nimage"->"Stub Storage": upload the stubs
"SCC Docker\nimage"->"SCC Docker": build successful
"SCC Docker"->"API Producer\nbuild": build successful
"API Producer\nbuild"->"API Producer": build successful
----

[[flows-provider-non-jvm-consumer]]
=== Consumer Flow

At a high level, the consumer:

. Sets up the build tool to:
* Start the Spring Cloud Contract Stub Runner Docker image and start the stubs.
+
The environment variables configure:
* The stubs to fetch.
* The location of the repositories.
+
Note that:
* To use the local storage, you can also attach it as a volume.
* The ports at which the stubs are running need to be exposed.
. Run the application tests against the running stubs.

The following UML diagram shows the consumer flow:

[plantuml, flows-provider-non-jvm-consumer, png]
----
"API Consumer"->"API Consumer\nbuild": run the build
"API Consumer\nbuild"->"SCC\nStub Runner\nDocker": set environment variables\ne.g. stub X running on port Y
"SCC\nStub Runner\nDocker"->"SCC\nStub Runner\nDocker\nimage": fetch and run\nthe stubs
"SCC\nStub Runner\nDocker\nimage"->"Stub Storage": fetch the stubs of X
"Stub Storage"->"SCC\nStub Runner\nDocker\nimage": stubs found
"SCC\nStub Runner\nDocker\nimage"->"X Stub": run the stub of X
"X Stub"->"SCC\nStub Runner\nDocker\nimage": stub is running\non port Y
"SCC\nStub Runner\nDocker\nimage"->"SCC\nStub Runner\nDocker": stubs running and\nready for tests
"API Consumer\nbuild"->"API Consumer\nbuild": run tests against X stub
"API Consumer\nbuild"->"X Stub": send a request
"X Stub"->"API Consumer\nbuild": response received
"API Consumer\nbuild"->"API Consumer": build successful
----

[[flows-provider-rest-docs]]
== Provider Contract Testing with REST Docs and Stubs in Nexus or Artifactory

In this flow, we do not use a Spring Cloud Contract plugin to generate tests and stubs. We write https://spring.io/projects/spring-restdocs[Spring RESTDocs], and, from them, we automatically generate stubs. Finally, we set up our builds to package the stubs and upload them to the stub storage site -- in our case, Nexus or Artifactory.

[[flows-provider-rest-docs-producer]]
=== Producer Flow

As a producer, we:

. Write RESTDocs tests of our API.
. Add Spring Cloud Contract Stub Runner starter to our build (`spring-cloud-starter-contract-stub-runner`), as follows:
+
====
[source,xml,indent=0,role="primary"]
.Maven
----
<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

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

[source,groovy,indent=0,role="secondary"]
.Gradle
----
dependencies {
	testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}
----
====
. We set up the build tool to package our stubs, as follows:
+
====
[source,xml,indent=0,role="primary"]
.Maven
----
<!-- pom.xml -->
<plugins>
	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-assembly-plugin</artifactId>
		<executions>
			<execution>
				<id>stub</id>
				<phase>prepare-package</phase>
				<goals>
					<goal>single</goal>
				</goals>
				<inherited>false</inherited>
				<configuration>
					<attach>true</attach>
					<descriptors>
						${basedir}/src/assembly/stub.xml
					</descriptors>
				</configuration>
			</execution>
		</executions>
	</plugin>
</plugins>

<!-- src/assembly/stub.xml -->
<assembly
	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
	<id>stubs</id>
	<formats>
		<format>jar</format>
	</formats>
	<includeBaseDirectory>false</includeBaseDirectory>
	<fileSets>
		<fileSet>
			<directory>${project.build.directory}/generated-snippets/stubs</directory>
			<outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings</outputDirectory>
			<includes>
				<include>**/*</include>
			</includes>
		</fileSet>
	</fileSets>
</assembly>
----

[source,groovy,indent=0,role="secondary"]
.Gradle
----
task stubsJar(type: Jar) {
	classifier = "stubs"
	into("META-INF/${project.group}/${project.name}/${project.version}/mappings") {
		include('**/*.*')
		from("${project.buildDir}/generated-snippets/stubs")
	}
}
// we need the tests to pass to build the stub jar
stubsJar.dependsOn(test)
bootJar.dependsOn(stubsJar)
----
====

Now, when we run the tests, stubs are automatically published and packaged.

The following UML diagram shows the producer flow:

[plantuml, flows-provider-rest-docs-producer, png]
----
"API Producer"->"API Producer": write RESTDocs tests
"API Producer"->"API Producer": add the stub runner\nstarter dependency
"API Producer"->"API Producer": setup the build tool to package\nthe generated stubs
"API Producer"->"API Producer\nbuild": run the build
"API Producer\nbuild"->"RESTDocs": generate HTTP snippets
"RESTDocs"->"Spring Cloud\nContract": generate HTTP stubs
"RESTDocs"->"Spring Cloud\nContract": (optional) generate\ncontract DSLs
"Spring Cloud\nContract"->"RESTDocs": files generated
"RESTDocs"->"API Producer\nbuild": snippets generated
"API Producer\nbuild"->"API Producer\nbuild": tests passed
"API Producer\nbuild"->"API Producer\nbuild": generate stubs jar
"API Producer\nbuild"->"Stub Storage": upload JAR with the application
"API Producer\nbuild"->"Stub Storage": upload JAR with the stubs
"Stub Storage"->"API Producer\nbuild": JARs uploaded
"API Producer\nbuild"->"API Producer": build successful
----

[[flows-provider-rest-docs-consumer]]
=== Consumer Flow

Since the consumer flow is not affected by the tool used to generate the stubs, you can read <<getting-started.adoc#getting-started-first-application-consumer, Developing Your First Spring Cloud Contract-based Application>> to see the flow for consumer side of the provider contract testing with stubs in Nexus or Artifactory.

[[using-whats-next]]
== What to Read Next

You should now understand how you can use {project-full-name} and some best practices that you
should follow. You can now go on to learn about specific
<<project-features#project-features, {project-full-name} features>>, or you could
skip ahead and read about the link:advanced.html[advanced features of {project-full-name}].
