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

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 this samples or this sample. As a result of pushing stubs there, the repository has the following structure:

$ 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 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 this sample.

The Flow

The flow looks exactly as the one presented in 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 How To page of the documentation.

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:

=== Annotation::

+

@AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
		repositoryRoot = "git://[email protected]:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git",
		ids = "com.example:artifact-id:0.0.1")
JUnit 4 Rule
@Rule
	public StubRunnerRule rule = new StubRunnerRule()
			.downloadStub("com.example","artifact-id", "0.0.1")
			.repoRoot("git://[email protected]:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
			.stubsMode(StubRunnerProperties.StubsMode.REMOTE);
JUnit 5 Extension
@RegisterExtension
	public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension()
			.downloadStub("com.example","artifact-id", "0.0.1")
			.repoRoot("git://[email protected]:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
			.stubsMode(StubRunnerProperties.StubsMode.REMOTE);

===

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:

=== 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://[email protected]: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>
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://[email protected]: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 How To section of the documentation.