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

include::partial$_attributes.adoc[]

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:
+
Maven::
+
[source,xml,indent=0,role="primary"]
----
<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>
----

Gradle::
+
[source,groovy,indent=0,role="secondary"]
----
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:
+
Maven::
+
[source,xml,indent=0,role="primary"]
----
<!-- 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>
----

Gradle::
+
[source,groovy,indent=0,role="secondary"]
----
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 xref:getting-started/first-application.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.
