diff --git a/spring-cloud-contract.html b/spring-cloud-contract.html
index 9b0d7b7508..f9b6b0a023 100644
--- a/spring-cloud-contract.html
+++ b/spring-cloud-contract.html
@@ -551,84 +551,8 @@ $(addBlockSwitches);
@@ -2074,7 +2002,9 @@ public void validate_shouldMarkClientAsFraud() throws Exception {
consumes = FRAUD_SERVICE_JSON_VERSION_1,
produces = FRAUD_SERVICE_JSON_VERSION_1)
public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
-Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.0.x/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=new_impl,indent=0]
+if (amountGreaterThanThreshold(fraudCheck)) {
+ return new FraudCheckResult(FraudCheckStatus.FRAUD, AMOUNT_TOO_HIGH);
+}
return new FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
}
@@ -2708,128 +2638,76 @@ Those poms are necessary for the consumer side to run mvn clean install -D
-
<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>project</id>
- <formats>
- <format>jar</format>
- </formats>
- <includeBaseDirectory>false</includeBaseDirectory>
- <fileSets>
- <fileSet>
- <directory>${project.basedir}</directory>
- <outputDirectory>/</outputDirectory>
- <useDefaultExcludes>true</useDefaultExcludes>
- <excludes>
- <exclude>**/${project.build.directory}/**</exclude>
- <exclude>mvnw</exclude>
- <exclude>mvnw.cmd</exclude>
- <exclude>.mvn/**</exclude>
- <exclude>src/**</exclude>
- </excludes>
- </fileSet>
- </fileSets>
-</assembly>
+
Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.0.x/samples/standalone/contracts/src/assembly/contracts.xml[indent=0]
+
+===== Workflow
+
+The workflow would look similar to the one presented in the `Step by step guide to CDC`. The only difference
+ is that the producer doesn't own the contracts anymore. So the consumer and the producer have to work on
+ common contracts in a common repository.
+
+====== Consumer
+
+When the *consumer* wants to work on the contracts offline, instead of cloning the producer code, the
+consumer team clones the common repository, goes to the required producer's folder (e.g. `com/example/server`)
+and runs `mvn clean install -DskipTests` to install locally the stubs converted from the contracts.
+
+TIP: You need to have http://maven.apache.org/download.cgi[Maven installed locally]
+
+====== Producer
+
+As a *producer* it's enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
+of the JAR containing the contracts:
+
+[source,xml,indent=0]
-
-
-
Workflow
-
The workflow would look similar to the one presented in the Step by step guide to CDC. The only difference
- is that the producer doesn’t own the contracts anymore. So the consumer and the producer have to work on
- common contracts in a common repository.
-
-
-
Consumer
-
-
When the consumer wants to work on the contracts offline, instead of cloning the producer code, the
-consumer team clones the common repository, goes to the required producer’s folder (e.g. com/example/server)
-and runs mvn clean install -DskipTests to install locally the stubs converted from the contracts.
-
-
-
-
-
Producer
-
-
As a producer it’s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
-of the JAR containing the contracts:
-
-
-
-
<plugin>
+<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
- <contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
+ <contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
<contractDependency>
<groupId>com.example.standalone</groupId>
<artifactId>contracts</artifactId>
</contractDependency>
</configuration>
-</plugin>
+</plugin>
-
-
-
With this setup the JAR with groupid com.example.standalone and artifactid contracts will be downloaded
-from http://link/to/your/nexus/or/artifactory/or/sth. It will be then unpacked in a local temporary folder
-and contracts present under the com/example/server will be picked as the ones used to generate the
-tests and the stubs. Due to this convention the producer team will know which consumer teams will be broken
-when some incompatible changes are done.
-
-
-
The rest of the flow looks the same.
-
-
-
-
-
-
Can I have multiple base classes for tests?
-
-
-
-
-
Spring Cloud Contract Verifier HTTP
-
-
Gradle Project
-
-
Prerequisites
-
-
In order to use Spring Cloud Contract Verifier with WireMock you have to use Gradle or Maven plugin.
-
-
-
-
-|
- Warning
- |
-
-If you want to use Spock in your projects you have to add separately
-the spock-core and spock-spring modules. Check Spock docs for more information
- |
-
-
-
-
-
Add gradle plugin with dependencies
-
buildscript {
+With this setup the JAR with groupid `com.example.standalone` and artifactid `contracts` will be downloaded
+from `http://link/to/your/nexus/or/artifactory/or/sth`. It will be then unpacked in a local temporary folder
+and contracts present under the `com/example/server` will be picked as the ones used to generate the
+tests and the stubs. Due to this convention the producer team will know which consumer teams will be broken
+when some incompatible changes are done.
+
+The rest of the flow looks the same.
+
+==== Can I have multiple base classes for tests?
+
+Yes! Check out the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_different_base_classes_for_contracts[Different base classes for contracts] sections
+of either Gradle or Maven plugins.
+
+=== Spring Cloud Contract Verifier HTTP
+
+==== Gradle Project
+
+===== Prerequisites
+
+In order to use Spring Cloud Contract Verifier with WireMock you have to use Gradle or Maven plugin.
+
+WARNING: If you want to use Spock in your projects you have to add separately
+the `spock-core` and `spock-spring` modules. Check http://spockframework.github.io/[Spock docs for more information]
+
+====== Add gradle plugin with dependencies
+
+[source,groovy,indent=0]
+
+
+
+
buildscript {
repositories {
mavenCentral()
}
@@ -2837,35 +2715,39 @@ the spock-core and spock-spring modules. Check
+
+
+
apply plugin: 'groovy'
+apply plugin: 'spring-cloud-contract'
+
+
+
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifier_version}"
}
-}
-
-dependencies {
+}
+
+
+
dependencies {
testCompile 'org.codehaus.groovy:groovy-all:2.4.6'
// example with adding Spock core and Spock Spring
testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4'
testCompile 'org.springframework.cloud:spring-cloud-starter-contract-verifier'
-}
-
-
-
-
-
Snapshot versions for Gradle
-
-
Add the additional snapshot repository to your build.gradle to use snapshot versions which are automatically uploaded after every successful build:
+}
-
buildscript {
+====== Snapshot versions for Gradle
+
+Add the additional snapshot repository to your build.gradle to use snapshot versions which are automatically uploaded after every successful build:
+
+[source,groovy,indent=0]
+
+
+
+
buildscript {
repositories {
mavenCentral()
mavenLocal()
@@ -2873,15 +2755,17 @@ dependencies {
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/release" }
}
-}
+}
-
-
-
-
Add maven plugin with dependencies
-
<dependencyManagement>
+====== Add maven plugin with dependencies
+
+[source,xml,indent=0]
+
+
+
+
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
@@ -2891,17 +2775,19 @@ dependencies {
<scope>import</scope>
</dependency>
</dependencies>
-</dependencyManagement>
-
-<dependencies>
+</dependencyManagement>
+
+
+
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
-</dependencies>
-
-<plugin>
+</dependencies>
+
+
+
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<executions>
@@ -2913,304 +2799,270 @@ dependencies {
</goals>
</execution>
</executions>
-</plugin>
+</plugin>
-
-
-
-
-
Add stubs
-
-
By default Spring Cloud Contract Verifier is looking for stubs in src/test/resources/contracts directory.
-
-
-
Directory containing stub definitions is treated as a class name, and each stub definition is treated as a single test.
+
+
+
Read more: https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/[spring-cloud-contract-maven-plugin]
+
+====== Add stubs
+
+By default Spring Cloud Contract Verifier is looking for stubs in `src/test/resources/contracts` directory.
+
+Directory containing stub definitions is treated as a class name, and each stub definition is treated as a single test.
We assume that it contains at least one directory which will be used as test class name. If there is more than one level of nested directories all except the last one will be used as package name.
-So with following structure
+So with following structure
+
+[source,groovy,indent=0]
+
+
+
+
src/test/resources/contracts/myservice/shouldCreateUser.groovy
+src/test/resources/contracts/myservice/shouldReturnUser.groovy
-
src/test/resources/contracts/myservice/shouldCreateUser.groovy
-src/test/resources/contracts/myservice/shouldReturnUser.groovy
+
Spring Cloud Contract Verifier will create test class `defaultBasePackage.MyService` with two methods
+
+ - `shouldCreateUser()`
+ - `shouldReturnUser()`
+
+===== Run plugin
+
+Plugin registers itself to be invoked before `check` task. You have nothing to do as long as you want it to be part of your build process. If you just want to generate tests please invoke `generateContractTests` task.
+
+===== Default setup
+
+Default Gradle Plugin setup creates the following Gradle part of the build (it's a pseudocode)
+
+[source,groovy,indent=0]
-
Spring Cloud Contract Verifier will create test class defaultBasePackage.MyService with two methods
-
-
-
--
-
shouldCreateUser()
-
--
-
shouldReturnUser()
-
-
-
-
-
-
-
Run plugin
-
-
Plugin registers itself to be invoked before check task. You have nothing to do as long as you want it to be part of your build process. If you just want to generate tests please invoke generateContractTests task.
-
-
-
-
Default setup
-
-
Default Gradle Plugin setup creates the following Gradle part of the build (it’s a pseudocode)
-
-
-
-
contracts {
+contracts {
targetFramework = 'JUNIT'
testMode = 'MockMvc'
generatedTestSourcesDir = project.file("${project.buildDir}/generated-test-sources/contracts")
contractsDslDir = "${project.rootDir}/src/test/resources/contracts"
basePackageForTests = 'org.springframework.cloud.verifier.tests'
- stubsOutputDir = project.file("${project.buildDir}/stubs")
-
- // the following properties are used when you want to provide where the JAR with contract lays
+ stubsOutputDir = project.file("${project.buildDir}/stubs")
+
+
+
+
// the following properties are used when you want to provide where the JAR with contract lays
contractDependency {
stringNotation = ''
}
contractsPath = ''
contractsWorkOffline = false
-}
-
-tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateClientStubs') {
+}
+
+
+
+
tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateClientStubs') {
baseName = project.name
classifier = contracts.stubsSuffix
from contractVerifier.stubsOutputDir
-}
-
-project.artifacts {
+}
+
+
+
project.artifacts {
archives task
-}
-
-tasks.create(type: Copy, name: 'copyContracts') {
+}
+
+
+
tasks.create(type: Copy, name: 'copyContracts') {
from contracts.contractsDslDir
into contracts.stubsOutputDir
-}
-
-verifierStubsJar.dependsOn 'copyContracts'
-
-publishing {
+}
+
+
+
verifierStubsJar.dependsOn 'copyContracts'
+
+
+
publishing {
publications {
stubs(MavenPublication) {
artifactId project.name
artifact verifierStubsJar
}
}
-}
-
-
-
-
-
-
-
To change default configuration just add contracts snippet to your Gradle config
+}
-
contracts {
+===== Configure plugin
+
+To change default configuration just add `contracts` snippet to your Gradle config
+
+[source,groovy,indent=0]
+
+
+
+
contracts {
testMode = 'MockMvc'
baseClassForTests = 'org.mycompany.tests'
generatedTestSourcesDir = project.file('src/generatedContract')
-}
-
-
-
-
Configuration options
-
-
--
-
testMode - defines mode for acceptance tests. By default MockMvc which is based on Spring’s MockMvc. It can also be changed to JaxRsClient or to Explicit for real HTTP calls.
-
--
-
imports - array with imports that should be included in generated tests (for example ['org.myorg.Matchers']). By default empty array []
-
--
-
staticImports - array with static imports that should be included in generated tests(for example ['org.myorg.Matchers.*']). By default empty array []
-
--
-
basePackageForTests - specifies base package for all generated tests. By default set to org.springframework.cloud.verifier.tests
-
--
-
baseClassForTests - base class for all generated tests. By default spock.lang.Specification if using Spock tests.
-
--
-
packageWithBaseClasses - instead of providing a fixed value for base class you can provide a package where all the base classes lay. Takes precedence over baseClassForTests.
-
--
-
baseClassMappings - explicitly map contract package to a FQN of a base class. Takes precedence over packageWithBaseClasses and baseClassForTests.
-
--
-
ruleClassForTests - specifies Rule which should be added to generated test classes.
-
--
-
ignoredFiles - Ant matcher allowing defining stub files for which processing should be skipped. By default empty array []
-
--
-
contractsDslDir - directory containing contracts written using the GroovyDSL. By default $rootDir/src/test/resources/contracts
-
--
-
generatedTestSourcesDir - test source directory where tests generated from Groovy DSL should be placed. By default $buildDir/generated-test-sources/contractVerifier
-
--
-
stubsOutputDir - dir where the generated WireMock stubs from Groovy DSL should be placed
-
--
-
targetFramework - the target test framework to be used; currently Spock and JUnit are supported with JUnit being the default framework
-
-
-
-
-
The following properties are used when you want to provide where the JAR with contract lays
-
-
-
--
-
contractDependency - the Dependency that provides groupid:artifactid:version:classifier coordinates. You can use the contractDependency closure to set it up
-
--
-
contractsPath - if contract deps are downloaded will default to groupid/artifactid where groupid will be slash separated. Otherwise will scan contracts under provided directory
-
--
-
contractsWorkOffline - in order not to download the dependencies each time you can download them once and work offline afterwards (reuse local Maven repo)
-
-
-
-
-
-
Single base class for all tests
-
-
When using Spring Cloud Contract Verifier in default MockMvc you need to create a base specification for all generated acceptance tests. In this class you need to point to endpoint which should be verified.
+}
-
abstract class BaseMockMvcSpec extends Specification {
+====== Configuration options
- def setup() {
- RestAssuredMockMvc.standaloneSetup(new PairIdController())
- }
+ - **testMode** - defines mode for acceptance tests. By default MockMvc which is based on Spring's MockMvc. It can also be changed to **JaxRsClient** or to **Explicit** for real HTTP calls.
+ - **imports** - array with imports that should be included in generated tests (for example ['org.myorg.Matchers']). By default empty array []
+ - **staticImports** - array with static imports that should be included in generated tests(for example ['org.myorg.Matchers.*']). By default empty array []
+ - **basePackageForTests** - specifies base package for all generated tests. By default set to org.springframework.cloud.verifier.tests
+ - **baseClassForTests** - base class for all generated tests. By default `spock.lang.Specification` if using Spock tests.
+ - **packageWithBaseClasses** - instead of providing a fixed value for base class you can provide a package where all the base classes lay. Takes precedence over **baseClassForTests**.
+ - **baseClassMappings** - explicitly map contract package to a FQN of a base class. Takes precedence over **packageWithBaseClasses** and **baseClassForTests**.
+ - **ruleClassForTests** - specifies Rule which should be added to generated test classes.
+ - **ignoredFiles** - Ant matcher allowing defining stub files for which processing should be skipped. By default empty array []
+ - **contractsDslDir** - directory containing contracts written using the GroovyDSL. By default `$rootDir/src/test/resources/contracts`
+ - **generatedTestSourcesDir** - test source directory where tests generated from Groovy DSL should be placed. By default `$buildDir/generated-test-sources/contractVerifier`
+ - **stubsOutputDir** - dir where the generated WireMock stubs from Groovy DSL should be placed
+ - **targetFramework** - the target test framework to be used; currently Spock and JUnit are supported with JUnit being the default framework
- void isProperCorrelationId(Integer correlationId) {
- assert correlationId == 123456
- }
+The following properties are used when you want to provide where the JAR with contract lays
- void isEmpty(String value) {
- assert value == null
- }
+ - **contractDependency** - the Dependency that provides `groupid:artifactid:version:classifier` coordinates. You can use the `contractDependency` closure to set it up
+ - **contractsPath** - if contract deps are downloaded will default to `groupid/artifactid` where `groupid` will be slash separated. Otherwise will scan contracts under provided directory
+ - **contractsWorkOffline** - in order not to download the dependencies each time you can download them once and work offline afterwards (reuse local Maven repo)
-}
+====== Single base class for all tests
+
+When using Spring Cloud Contract Verifier in default MockMvc you need to create a base specification for all generated acceptance tests. In this class you need to point to endpoint which should be verified.
+
+[source,groovy,indent=0]
-
In case of using Explicit mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of JAXRSCLIENT mode this base class
-should also contain protected WebTarget webTarget field, right now the only option to test JAX-RS API is to start a web server.
+
abstract class BaseMockMvcSpec extends Specification {
+
+
+
+
def setup() {
+ RestAssuredMockMvc.standaloneSetup(new PairIdController())
+}
-
-
Different base classes for contracts
-
-
If your base classes differ between contracts you can tell the Spring Cloud Contract plugin which class should get
-extended by the autogenerated tests. You have two options:
+
+
+
void isProperCorrelationId(Integer correlationId) {
+ assert correlationId == 123456
+}
+
+
+
+
+
void isEmpty(String value) {
+ assert value == null
+}
-
-
-
The convention is such that if you have a contract under e.g. src/test/resources/contract/foo/bar/baz/ and provide the value of the packageWithBaseClasses property
-to com.example.base then we will assume that there is a BarBazBase class under com.example.base package. In other words we take last two parts of package
-if they exist and form a class with a Base suffix. Takes precedence over baseClassForTests. Example of usage in the contracts closure:
+
}
-
packageWithBaseClasses = 'com.example.base'
+
In case of using `Explicit` mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of `JAXRSCLIENT` mode this base class
+should also contain `protected WebTarget webTarget` field, right now the only option to test JAX-RS API is to start a web server.
+
+====== Different base classes for contracts
+
+If your base classes differ between contracts you can tell the Spring Cloud Contract plugin which class should get
+extended by the autogenerated tests. You have two options:
+
+ - follow a convention by providing the `packageWithBaseClasses`
+ - provide explicit mapping via `baseClassMappings`
+
+*Convention*
+
+The convention is such that if you have a contract under e.g. `src/test/resources/contract/foo/bar/baz/` and provide the value of the `packageWithBaseClasses` property
+to `com.example.base` then we will assume that there is a `BarBazBase` class under `com.example.base` package. In other words we take last two parts of package
+if they exist and form a class with a `Base` suffix. Takes precedence over **baseClassForTests**. Example of usage in the `contracts` closure:
+
+[source,groovy,indent=0]
-
-
You can manually map a regular expression of the contract’s package to fully qualified name of the base class for the matched contract.
-Let’s take a look at the following example:
+
packageWithBaseClasses = 'com.example.base'
-
baseClassForTests = "com.example.FooBase"
+*Mapping*
+
+You can manually map a regular expression of the contract's package to fully qualified name of the base class for the matched contract.
+Let's take a look at the following example:
+
+[source,groovy,indent=0]
+
+
+
+
baseClassForTests = "com.example.FooBase"
baseClassMappings {
- baseClassMapping('.*/com/.*', 'com.example.ComBase')
- baseClassMapping('.*/bar/.*':'com.example.BarBase')
-}
-
-
-
-
Let’s assume that you have contracts under
- - src/test/resources/contract/com/
- - src/test/resources/contract/foo/
-
-
-
By providing the baseClassForTests we have a fallback in case mapping didn’t succeed (you could also provide
-the packageWithBaseClasses as fallback). That way the tests generated from src/test/resources/contract/com/ contracts
-will be extending the com.example.ComBase whereas the rest of tests will extend com.example.FooBase.
-
-
-
-
-
Invoking generated tests
-
-
To ensure that provider side is complaint with defined contracts, you need to invoke:
+ baseClassMapping('.
/com/.', 'com.example.ComBase')
+ baseClassMapping('.
/bar/.':'com.example.BarBase')
+}
-
./gradlew generateContractTests test
+
Let's assume that you have contracts under
+ - `src/test/resources/contract/com/`
+ - `src/test/resources/contract/foo/`
+
+By providing the `baseClassForTests` we have a fallback in case mapping didn't succeed (you could also provide
+the `packageWithBaseClasses` as fallback). That way the tests generated from `src/test/resources/contract/com/` contracts
+will be extending the `com.example.ComBase` whereas the rest of tests will extend `com.example.FooBase`.
+
+===== Invoking generated tests
+
+To ensure that provider side is complaint with defined contracts, you need to invoke:
+
+[source,bash,indent=0]
-
-
-
Spring Cloud Contract Verifier on consumer side
-
-
In consumer service you need to configure Spring Cloud Contract Verifier plugin in exactly the same way as in case of provider. If you don’t want to use Stub Runner then you need to copy contracts stored in
-src/test/resources/contracts and generate WireMock json stubs using:
-
+
/gradlew generateContractTests test
-
./gradlew generateClientStubs
+
===== Spring Cloud Contract Verifier on consumer side
+
+In consumer service you need to configure Spring Cloud Contract Verifier plugin in exactly the same way as in case of provider. If you don't want to use Stub Runner then you need to copy contracts stored in
+`src/test/resources/contracts` and generate WireMock json stubs using:
+
+[source,bash,indent=0]
-
-
Note that stubsOutputDir option has to be set for stub generation to work.
-
-
-
When present, json stubs can be used in consumer automated tests.
-
+
/gradlew generateClientStubs
-
@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application)
-class LoanApplicationServiceSpec extends Specification {
+Note that `stubsOutputDir` option has to be set for stub generation to work.
- @ClassRule
- @Shared
- WireMockClassRule wireMockRule == new WireMockClassRule()
+When present, json stubs can be used in consumer automated tests.
- @Autowired
- LoanApplicationService sut
-
- def 'should successfully apply for loan'() {
+[source,groovy,indent=0]
+
+
+
+
@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application)
+class LoanApplicationServiceSpec extends Specification {
+
+
+
+
@ClassRule
+@Shared
+WireMockClassRule wireMockRule == new WireMockClassRule()
+
+
+
+
+
@Autowired
+LoanApplicationService sut
+
+
+
+
+
def 'should successfully apply for loan'() {
given:
LoanApplication application =
new LoanApplication(client: new Client(clientPesel: '12345678901'), amount: 123.123)
@@ -3220,24 +3072,24 @@ class LoanApplicationServiceSpec extends Specification {
loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED
loanApplication.rejectionReason == null
}
-}
+}
-
-
Underneath LoanApplication makes a call to FraudDetection service. This request is handled by WireMock server configured using stubs generated by Spring Cloud Contract Verifier.
-
-
-
-
-
Using in your Maven project
-
-
Add maven plugin
-
-
Add the Spring Cloud Contract BOM
-
-
<dependencyManagement>
+Underneath LoanApplication makes a call to FraudDetection service. This request is handled by WireMock server configured using stubs generated by Spring Cloud Contract Verifier.
+
+==== Using in your Maven project
+
+===== Add maven plugin
+
+Add the Spring Cloud Contract BOM
+
+[source,xml,indent=0]
+
+
+
+
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
@@ -3247,15 +3099,17 @@ class LoanApplicationServiceSpec extends Specification {
<scope>import</scope>
</dependency>
</dependencies>
-</dependencyManagement>
-
-
-
-
Next, the Spring Cloud Contract Verifier Maven plugin
+</dependencyManagement>
-
<plugin>
+Next, the `Spring Cloud Contract Verifier` Maven plugin
+
+[source,xml,indent=0]
+
+
+
+
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
@@ -3263,24 +3117,25 @@ class LoanApplicationServiceSpec extends Specification {
<configuration>
<packageWithBaseClasses>com.example.fraud</packageWithBaseClasses>
</configuration>
-</plugin>
-
-
-
-
-
Snapshot versions for Maven
-
-
For Snapshot / Milestone versions you have to add the following section to your pom.xml
+</plugin>
-
<repositories>
+You can read more in the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/[Spring Cloud Contract Maven Plugin Docs]
+
+====== Snapshot versions for Maven
+
+For Snapshot / Milestone versions you have to add the following section to your `pom.xml`
+
+[source,xml,indent=0]
+
+
+
+
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
- <url>https://repo.spring.io/snapshot</url>
+ <url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -3288,7 +3143,7 @@ class LoanApplicationServiceSpec extends Specification {
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
- <url>https://repo.spring.io/milestone</url>
+ <url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -3296,7 +3151,7 @@ class LoanApplicationServiceSpec extends Specification {
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
- <url>https://repo.spring.io/release</url>
+ <url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -3306,7 +3161,7 @@ class LoanApplicationServiceSpec extends Specification {
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
- <url>https://repo.spring.io/snapshot</url>
+ <url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -3314,7 +3169,7 @@ class LoanApplicationServiceSpec extends Specification {
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
- <url>https://repo.spring.io/milestone</url>
+ <url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -3322,50 +3177,48 @@ class LoanApplicationServiceSpec extends Specification {
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
- <url>https://repo.spring.io/release</url>
+ <url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
-</pluginRepositories>
+</pluginRepositories>
-
-
-
-
-
Add stubs
-
-
By default Spring Cloud Contract Verifier is looking for stubs in src/test/resources/contracts directory.
+
+
+
===== Add stubs
+
+By default Spring Cloud Contract Verifier is looking for stubs in `src/test/resources/contracts` directory.
Directory containing stub definitions is treated as a class name, and each stub definition is treated as a single test.
We assume that it contains at least one directory which will be used as test class name. If there is more than one level of nested directories all except the last one will be used as package name.
-So with following structure
+So with following structure
+
+[source,groovy,indent=0]
+
+
+
+
src/test/resources/contracts/myservice/shouldCreateUser.groovy
+src/test/resources/contracts/myservice/shouldReturnUser.groovy
-
src/test/resources/contracts/myservice/shouldCreateUser.groovy
-src/test/resources/contracts/myservice/shouldReturnUser.groovy
+
Spring Cloud Contract Verifier will create test class `defaultBasePackage.MyService` with two methods
+ - `shouldCreateUser()`
+ - `shouldReturnUser()`
+
+===== Run plugin
+
+Plugin goal `generateTests` is assigned to be invoked in phase `generate-test-sources`. You have nothing to do as long as you want it to be part of your build process. If you just want to generate tests please invoke `generateTests` goal.
+
+===== Configure plugin
+
+To change default configuration just add `configuration` section to plugin definition or `execution` definition.
+
+[source,xml,indent=0]
-
Spring Cloud Contract Verifier will create test class defaultBasePackage.MyService with two methods
- - shouldCreateUser()
- - shouldReturnUser()
-
-
-
-
Run plugin
-
-
Plugin goal generateTests is assigned to be invoked in phase generate-test-sources. You have nothing to do as long as you want it to be part of your build process. If you just want to generate tests please invoke generateTests goal.
-
-
-
-
-
-
To change default configuration just add configuration section to plugin definition or execution definition.
-
-
-
-
<plugin>
+<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<executions>
@@ -3381,177 +3234,137 @@ src/test/resources/contracts/myservice/shouldReturnUser.groovy
<basePackageForTests>org.springframework.cloud.verifier.twitter.place</basePackageForTests>
<baseClassForTests>org.springframework.cloud.verifier.twitter.place.BaseMockMvcSpec</baseClassForTests>
</configuration>
-</plugin>
-
-
-
-
Important configuration options
-
-
--
-
testMode - defines mode for acceptance tests. By default MockMvc which is based on Spring’s MockMvc. It can also be changed to JaxRsClient or to Explicit for real HTTP calls.
-
--
-
basePackageForTests - specifies base package for all generated tests. By default set to org.springframework.cloud.verifier.tests.
-
--
-
ruleClassForTests - specifies Rule which should be added to generated test classes.
-
--
-
baseClassForTests - base class for generated tests. By default spock.lang.Specification if using Spock tests.
-
--
-
contractsDir - directory containing contracts written using the GroovyDSL. By default /src/test/resources/contracts.
-
--
-
testFramework - the target test framework to be used; currently Spock and JUnit are supported with JUnit being the default framework
-
--
-
packageWithBaseClasses - instead of providing a fixed value for base class you can provide a package where all the base classes lay.
-The convention is such that if you have a contract under src/test/resources/contract/foo/bar/baz/ and provide the value of this property
-to com.example.base then we will assume that there is a BarBazBase class under com.example.base package. Takes precedence
-over baseClassForTests
-
--
-
baseClassMappings - list of base class mappings that where you have to provide contractPackageRegex which is checked
-against the package in which the contract lays and baseClassFQN that maps to fully qualified name of the base class for the matched
-contract. If you have a contract under src/test/resources/contract/foo/bar/baz/ and map the property .* → com.example.base.BaseClass then
-the test class generated from these contracts will extend com.example.base.BaseClass. Takes precedence over packageWithBaseClasses
- and baseClassForTests.
-
-
-
-
-
If you want to download your contract definitions from a Maven repository you can use
-
-
-
--
-
contractsRepositoryUrl - URL to a repo with the artifacts with contracts, if not provided should use the current Maven ones
-
--
-
contractDependency - the contract dependency that contains all the packaged contracts
-
--
-
contractsPath - path to concrete contracts in the JAR with packaged contracts. Defaults to groupid/artifactid where gropuid is slash separated.
-
--
-
contractsWorkOffline - if the dependencies should be downloaded or local Maven only should be reused
-
-
-
-
-
-
-
Single base class for all tests
-
-
When using Spring Cloud Contract Verifier in default MockMvc you need to create a base specification for all generated acceptance tests.
-In this class you need to point to endpoint which should be verified.
+</plugin>
-
package org.mycompany.tests
+====== Important configuration options
-import org.mycompany.ExampleSpringController
+ - **testMode** - defines mode for acceptance tests. By default `MockMvc` which is based on Spring's MockMvc. It can also be changed to `JaxRsClient` or to `Explicit` for real HTTP calls.
+ - **basePackageForTests** - specifies base package for all generated tests. By default set to `org.springframework.cloud.verifier.tests`.
+ - **ruleClassForTests** - specifies Rule which should be added to generated test classes.
+ - **baseClassForTests** - base class for generated tests. By default `spock.lang.Specification` if using Spock tests.
+ - **contractsDir** - directory containing contracts written using the GroovyDSL. By default `/src/test/resources/contracts`.
+ - **testFramework** - the target test framework to be used; currently Spock and JUnit are supported with JUnit being the default framework
+ - **packageWithBaseClasses** - instead of providing a fixed value for base class you can provide a package where all the base classes lay.
+ The convention is such that if you have a contract under `src/test/resources/contract/foo/bar/baz/` and provide the value of this property
+ to `com.example.base` then we will assume that there is a `BarBazBase` class under `com.example.base` package. Takes precedence
+ over **baseClassForTests**
+ - **baseClassMappings** - list of base class mappings that where you have to provide `contractPackageRegex` which is checked
+ against the package in which the contract lays and `baseClassFQN` that maps to fully qualified name of the base class for the matched
+ contract. If you have a contract under `src/test/resources/contract/foo/bar/baz/` and map the property `.*` -> `com.example.base.BaseClass` then
+ the test class generated from these contracts will extend `com.example.base.BaseClass`. Takes precedence over **packageWithBaseClasses**
+ and **baseClassForTests**.
+
+If you want to download your contract definitions from a Maven repository you can use
+
+ - **contractsRepositoryUrl** - URL to a repo with the artifacts with contracts, if not provided should use the current Maven ones
+ - **contractDependency** - the contract dependency that contains all the packaged contracts
+ - **contractsPath** - path to concrete contracts in the JAR with packaged contracts. Defaults to `groupid/artifactid` where `gropuid` is slash separated.
+ - **contractsWorkOffline** - if the dependencies should be downloaded or local Maven only should be reused
+
+For complete information take a look at https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/plugin-info.html[Plugin Documentation]
+
+====== Single base class for all tests
+
+When using Spring Cloud Contract Verifier in default MockMvc you need to create a base specification for all generated acceptance tests.
+In this class you need to point to endpoint which should be verified.
+
+[source,groovy,indent=0]
+
+
+
+
package org.mycompany.tests
+
+
+
import org.mycompany.ExampleSpringController
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
-import spock.lang.Specification
-
-class MvcSpec extends Specification {
+import spock.lang.Specification
+
+
+
class MvcSpec extends Specification {
def setup() {
RestAssuredMockMvc.standaloneSetup(new ExampleSpringController())
}
-}
-
-
-
-
In case of using Explicit mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of JAXRSCLIENT mode this base class should also contain protected WebTarget webTarget field, right now the only option to test JAX-RS API is to start a web server.
-
-
-
-
Different base classes for contracts
-
-
If your base classes differ between contracts you can tell the Spring Cloud Contract plugin which class should get
-extended by the autogenerated tests. You have two options:
-
-
-
-
-
The convention is such that if you have a contract under e.g. src/test/resources/contract/hello/v1/ and provide the value of the packageWithBaseClasses property
-to hello then we will assume that there is a HelloV1Base class under hello package. In other words we take last two parts of package
-if they exist and form a class with a Base suffix. Takes precedence over baseClassForTests. Example of usage:
+}
-
<plugin>
+In case of using `Explicit` mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of `JAXRSCLIENT` mode this base class should also contain `protected WebTarget webTarget` field, right now the only option to test JAX-RS API is to start a web server.
+
+====== Different base classes for contracts
+
+If your base classes differ between contracts you can tell the Spring Cloud Contract plugin which class should get
+extended by the autogenerated tests. You have two options:
+
+ - follow a convention by providing the `packageWithBaseClasses`
+ - provide explicit mapping via `baseClassMappings`
+
+*Convention*
+
+The convention is such that if you have a contract under e.g. `src/test/resources/contract/hello/v1/` and provide the value of the `packageWithBaseClasses` property
+to `hello` then we will assume that there is a `HelloV1Base` class under `hello` package. In other words we take last two parts of package
+if they exist and form a class with a `Base` suffix. Takes precedence over **baseClassForTests**. Example of usage:
+
+[source,xml,indent=0]
+
+
+
+
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<packageWithBaseClasses>hello</packageWithBaseClasses>
</configuration>
-</plugin>
-
-
-
-
-
You can manually map a regular expression of the contract’s package to fully qualified name of the base class for the matched contract.
-You have to provide a list baseClassMappings of baseClassMapping that takes a contractPackageRegex to baseClassFQN mapping.
-Let’s take a look at the following example:
+</plugin>
-
<plugin>
+*Mapping*
+
+You can manually map a regular expression of the contract's package to fully qualified name of the base class for the matched contract.
+You have to provide a list `baseClassMappings` of `baseClassMapping` that takes a `contractPackageRegex` to `baseClassFQN` mapping.
+Let's take a look at the following example:
+
+[source,xml,indent=0]
+
+
+
+
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<baseClassForTests>com.example.FooBase</baseClassForTests>
<baseClassMappings>
<baseClassMapping>
- <contractPackageRegex>.*com.*</contractPackageRegex>
+ <contractPackageRegex>.com.</contractPackageRegex>
<baseClassFQN>com.example.TestBase</baseClassFQN>
</baseClassMapping>
</baseClassMappings>
</configuration>
-</plugin>
-
-
-
-
Let’s assume that you have contracts under
- - src/test/resources/contract/com/
- - src/test/resources/contract/foo/
-
-
-
By providing the baseClassForTests we have a fallback in case mapping didn’t succeed (you could also provide
-the packageWithBaseClasses as fallback). That way the tests generated from src/test/resources/contract/com/ contracts
-will be extending the com.example.ComBase whereas the rest of tests will extend com.example.FooBase.
-
-
-
-
-
Invoking generated tests
-
-
Spring Cloud Contract Maven Plugin generates verification code into directory /generated-test-sources/contractVerifier and attach this directory to testCompile goal.
-
-
-
For Groovy Spock code use:
+</plugin>
-
<plugin>
+Let's assume that you have contracts under
+ - `src/test/resources/contract/com/`
+ - `src/test/resources/contract/foo/`
+
+By providing the `baseClassForTests` we have a fallback in case mapping didn't succeed (you could also provide
+the `packageWithBaseClasses` as fallback). That way the tests generated from `src/test/resources/contract/com/` contracts
+will be extending the `com.example.ComBase` whereas the rest of tests will extend `com.example.FooBase`.
+
+===== Invoking generated tests
+
+Spring Cloud Contract Maven Plugin generates verification code into directory `/generated-test-sources/contractVerifier` and attach this directory to `testCompile` goal.
+
+For Groovy Spock code use:
+
+[source,xml,indent=0]
+
+
+
+
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.5</version>
@@ -3567,43 +3380,42 @@ will be extending the com.example.ComBase whereas the rest of tests
<testSource>
<directory>${project.basedir}/src/test/groovy</directory>
<includes>
- <include>**/*.groovy</include>
+ <include>/.groovy</include>
</includes>
</testSource>
<testSource>
<directory>${project.build.directory}/generated-test-sources/contractVerifier</directory>
<includes>
- <include>**/*.groovy</include>
+ <include>/.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
-</plugin>
-
-
-
-
To ensure that provider side is complaint with defined contracts, you need to invoke mvn generateTest test
-
-
-
-
Spring Cloud Contract Verifier on consumer side
-
-
You can actually use the Spring Cloud Contract Verifier also for the consumer side!
-You can use the plugin so that it only converts the contracts and generates the stubs.
-To achieve that you need to configure Spring Cloud Contract Verifier plugin in exactly
-the same way as in case of provider. You need to copy contracts stored in
-src/test/resources/contracts and generate WireMock json stubs using:
-mvn generateStubs command. By default generated WireMock mapping is
-stored in directory target/mappings. Your project should create from
-this generated mappings additional artifact with classifier stubs for
-easy deploy to maven repository.
-
-
-
Sample configuration:
+</plugin>
-
<plugin>
+To ensure that provider side is complaint with defined contracts, you need to invoke `mvn generateTest test`
+
+===== Spring Cloud Contract Verifier on consumer side
+
+You can actually use the Spring Cloud Contract Verifier also for the consumer side!
+You can use the plugin so that it only converts the contracts and generates the stubs.
+To achieve that you need to configure Spring Cloud Contract Verifier plugin in exactly
+the same way as in case of provider. You need to copy contracts stored in
+`src/test/resources/contracts` and generate WireMock json stubs using:
+`mvn generateStubs` command. By default generated WireMock mapping is
+stored in directory `target/mappings`. Your project should create from
+this generated mappings additional artifact with classifier `stubs` for
+easy deploy to maven repository.
+
+Sample configuration:
+
+[source,xml,indent=0]
+
+
+
+
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${verifier-plugin.version}</version>
@@ -3615,23 +3427,30 @@ easy deploy to maven repository.
</goals>
</execution>
</executions>
-</plugin>
-
-
-
-
When present, json stubs can be used in consumer automated tests.
+</plugin>
-
@RunWith(SpringTestRunner.class)
+When present, json stubs can be used in consumer automated tests.
+
+[source,groovy,indent=0]
+
+
+
+
@RunWith(SpringTestRunner.class)
@SpringBootTest
@AutoConfigureStubRunner
-public class LoanApplicationServiceTests {
-
- @Autowired
- LoanApplicationService service;
-
- @Test
+public class LoanApplicationServiceTests {
+
+
+
+
@Autowired
+LoanApplicationService service;
+
+
+
+
+
@Test
public void shouldSuccessfullyApplyForLoan() {
//given:
LoanApplication application =
@@ -3642,212 +3461,151 @@ public class LoanApplicationServiceTests {
assertThat(loanApplication.loanApplicationStatus).isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
assertThat(loanApplication.rejectionReason).isNull();
}
-}
+}
-
-
Underneath LoanApplication makes a call to the FraudDetection service. This request is handled by
-a WireMock server configured using stubs generated by Spring Cloud Contract Verifier.
-
-
-
-
-
Scenarios
-
-
It’s possible to handle scenarios with Spring Cloud Contract Verifier. All you need to do is to stick to proper naming convention while creating your contracts. The convention requires to include order number followed by the underscore.
-
-
my_contracts_dir\
+Underneath `LoanApplication` makes a call to the `FraudDetection` service. This request is handled by
+a WireMock server configured using stubs generated by Spring Cloud Contract Verifier.
+
+==== Scenarios
+
+It's possible to handle scenarios with Spring Cloud Contract Verifier. All you need to do is to stick to proper naming convention while creating your contracts. The convention requires to include order number followed by the underscore.
+
+[source,indent=0]
+
+
+
+
my_contracts_dir\
scenario1\
1_login.groovy
2_showCart.groovy
- 3_logout.groovy
-
-
-
-
Such tree will cause Spring Cloud Contract Verifier generating WireMock’s scenario with name scenario1 and three steps:
-
-
-
--
-
login marked as Started pointing to:
-
--
-
showCart marked as Step1 pointing to:
-
--
-
logout marked as Step2 which will close the scenario.
-
-
-
-
-
-
Spring Cloud Contract Verifier will also generate tests with guaranteed order of execution.
-
-
-
-
Stubs and transitive dependencies
-
-
The Maven and Gradle plugin that we’re created are adding the tasks that create the stubs jar for you. What can be problematic
-is that when reusing the stubs you can by mistake import all of that stub dependencies! When building a Maven artifact
-even though you have a couple of different jars, all of them share one pom:
+ 3_logout.groovy
-
├── github-webhook-0.0.1.BUILD-20160903.075506-1-stubs.jar
+Such tree will cause Spring Cloud Contract Verifier generating WireMock's scenario with name `scenario1` and three steps:
+
+ - login marked as `Started` pointing to:
+ - showCart marked as `Step1` pointing to:
+ - logout marked as `Step2` which will close the scenario.
+
+More details about WireMock scenarios can be found under http://wiremock.org/stateful-behaviour.html[http://wiremock.org/stateful-behaviour.html]
+
+Spring Cloud Contract Verifier will also generate tests with guaranteed order of execution.
+
+==== Stubs and transitive dependencies
+
+The Maven and Gradle plugin that we're created are adding the tasks that create the stubs jar for you. What can be problematic
+is that when reusing the stubs you can by mistake import all of that stub dependencies! When building a Maven artifact
+even though you have a couple of different jars, all of them share one pom:
+
+[source,bash,indent=0]
+
+
+
+
├── github-webhook-0.0.1.BUILD-20160903.075506-1-stubs.jar
├── github-webhook-0.0.1.BUILD-20160903.075506-1-stubs.jar.sha1
├── github-webhook-0.0.1.BUILD-20160903.075655-2-stubs.jar
├── github-webhook-0.0.1.BUILD-20160903.075655-2-stubs.jar.sha1
├── github-webhook-0.0.1.BUILD-SNAPSHOT.jar
├── github-webhook-0.0.1.BUILD-SNAPSHOT.pom
├── github-webhook-0.0.1.BUILD-SNAPSHOT-stubs.jar
-├── ...
-└── ...
-
-
-
-
There are three possibilities of working with those dependencies so as not to have any issues with transitive dependencies.
-
-
-
Mark all application dependencies as optional
-
-
-
If in the github-webhook application we would mark all of our dependencies as optional, when you include the
-github-webhook stubs in another application (or when that dependency gets downloaded by Stub Runner) then, since
-all of the depenencies are optional, they will not get downloaded.
-
-
-
Create a separate artifactid for stubs
-
-
-
If you create a separate artifactid then you can set it up in whatever way you wish. For example by having no dependencies at all.
-
-
-
Exclude dependencies on the consumer side
-
-
-
As a consumer, if you add the stub dependency to your classpath you can explicitly exclude the unwanted dependencies.
-
-
-
-
-
Spring Cloud Contract Verifier Messaging
-
-
Spring Cloud Contract Verifier allows you to verify your application that uses messaging as means of communication.
-All of our integrations are working with Spring but you can also create one yourself and use it.
-
-
-
Integrations
-
-
You can use one of the four integration configurations:
-
-
-
--
-
Apache Camel
-
--
-
Spring Integration
-
--
-
Spring Cloud Stream
-
--
-
Spring AMQP
-
-
-
-
-
Since we’re using Spring Boot then if you have added one of the aforementioned libraries
-to the classpath then automatically all the messaging configuration will be set up.
-
-
-
-
-|
- Important
- |
-
-Remember to put @AutoConfigureMessageVerifier on the base class of your
-generated tests. Otherwise messaging part of Spring Cloud Contract Verifier will not work.
- |
-
-
-
-
-
-
Manual Integration Testing
-
-
The main interface used by the tests is the org.springframework.cloud.contract.verifier.messaging.MessageVerifier.
-It defines how to send and receive messages. You can create your own implementation to achieve the
-same goal.
-
-
-
In the a test you can inject a ContractVerifierMessageExchange to send and receive messages that follow the contract.
-Then add @AutoConfigureMessageVerifier to your test, e.g.
+├── …
+└── …
-
@RunWith(SpringTestRunner.class)
+There are three possibilities of working with those dependencies so as not to have any issues with transitive dependencies.
+
+*Mark all application dependencies as optional*
+
+If in the `github-webhook` application we would mark all of our dependencies as optional, when you include the
+`github-webhook` stubs in another application (or when that dependency gets downloaded by Stub Runner) then, since
+all of the depenencies are optional, they will not get downloaded.
+
+*Create a separate artifactid for stubs*
+
+If you create a separate artifactid then you can set it up in whatever way you wish. For example by having no dependencies at all.
+
+*Exclude dependencies on the consumer side*
+
+As a consumer, if you add the stub dependency to your classpath you can explicitly exclude the unwanted dependencies.
+
+=== Spring Cloud Contract Verifier Messaging
+
+Spring Cloud Contract Verifier allows you to verify your application that uses messaging as means of communication.
+All of our integrations are working with Spring but you can also create one yourself and use it.
+
+==== Integrations
+
+You can use one of the four integration configurations:
+
+- Apache Camel
+- Spring Integration
+- Spring Cloud Stream
+- Spring AMQP
+
+Since we're using Spring Boot then if you have added one of the aforementioned libraries
+to the classpath then automatically all the messaging configuration will be set up.
+
+IMPORTANT: Remember to put `@AutoConfigureMessageVerifier` on the base class of your
+generated tests. Otherwise messaging part of Spring Cloud Contract Verifier will not work.
+
+==== Manual Integration Testing
+
+The main interface used by the tests is the `org.springframework.cloud.contract.verifier.messaging.MessageVerifier`.
+It defines how to send and receive messages. You can create your own implementation to achieve the
+same goal.
+
+In the a test you can inject a `ContractVerifierMessageExchange` to send and receive messages that follow the contract.
+Then add `@AutoConfigureMessageVerifier` to your test, e.g.
+
+[source,java,indent=0]
+
+
+
+
@RunWith(SpringTestRunner.class)
@SpringBootTest
@AutoConfigureMessageVerifier
-public static class MessagingContractTests {
-
- @Autowired
+public static class MessagingContractTests {
+
+
+
+
@Autowired
private MessageVerifier verifier;
...
-}
+}
-
-
-
-|
- Note
- |
-
-If your tests require stubs as well, then
-@AutoConfigureStubRunner includes the messaging configuration, so
-you only need the one annotation.
- |
-
-
-
-
-
-
Publisher side test generation
-
-
Having the input or outputMessage sections in your DSL will result in creation of tests on the publisher’s side. By default
-JUnit tests will be created, however there is also a possibility to create Spock tests.
-
-
-
There are 3 main scenarios that we should take into consideration:
-
-
-
--
-
Scenario 1: there is no input message that produces an output one. The output message is triggered by a component
-inside the application (e.g. scheduler)
-
--
-
Scenario 2: the input message triggers an output message
-
--
-
Scenario 3: the input message is consumed and there is no output message
-
-
-
-
-
-
-
For the given contract:
-
-
def contractDsl = Contract.make {
+NOTE: If your tests require stubs as well, then
+`@AutoConfigureStubRunner` includes the messaging configuration, so
+you only need the one annotation.
+
+==== Publisher side test generation
+
+Having the `input` or `outputMessage` sections in your DSL will result in creation of tests on the publisher's side. By default
+JUnit tests will be created, however there is also a possibility to create Spock tests.
+
+There are 3 main scenarios that we should take into consideration:
+
+- Scenario 1: there is no input message that produces an output one. The output message is triggered by a component
+inside the application (e.g. scheduler)
+- Scenario 2: the input message triggers an output message
+- Scenario 3: the input message is consumed and there is no output message
+
+===== Scenario 1 (no input message)
+
+For the given contract:
+
+[source,groovy]
+
+
+
+
def contractDsl = Contract.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
@@ -3859,57 +3617,71 @@ inside the application (e.g. scheduler)
header('BOOK-NAME', 'foo')
}
}
-}
-
-
-
-
The following JUnit test will be created:
+}
-
'''
- // when:
- bookReturnedTriggered();
+The following JUnit test will be created:
- // then:
+[source,groovy]
+
+
+
+
+
+
// when:
+ bookReturnedTriggered();
+
+
+
+
+
// then:
ContractVerifierMessage response = contractVerifierMessaging.receive("activemq:output");
assertThat(response).isNotNull();
assertThat(response.getHeader("BOOK-NAME")).isEqualTo("foo");
// and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
-'''
+'''
-
-
And the following Spock test would be created:
-
-
'''
- when:
- bookReturnedTriggered()
+And the following Spock test would be created:
- then:
- ContractVerifierMessage response = contractVerifierMessaging.receive('activemq:output')
- assert response != null
- response.getHeader('BOOK-NAME') == 'foo'
- and:
- DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
- assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
-
-'''
+[source,groovy]
+
+
+
+
when:
+ bookReturnedTriggered()
-
-
-
+
+
+
then:
+ ContractVerifierMessage response = contractVerifierMessaging.receive('activemq:output')
+ assert response != null
+ response.getHeader('BOOK-NAME') == 'foo'
+and:
+ DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
+ assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
+
+
+
-
def contractDsl = Contract.make {
+===== Scenario 2 (output triggered by input)
+
+For the given contract:
+
+[source,groovy]
+
+
+
+
def contractDsl = Contract.make {
label 'some_label'
input {
messageFrom('jms:input')
@@ -3929,68 +3701,80 @@ inside the application (e.g. scheduler)
header('BOOK-NAME', 'foo')
}
}
-}
-
-
-
-
The following JUnit test will be created:
+}
-
'''
-// given:
- ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
+The following JUnit test will be created:
+
+[source,groovy]
+
+
+
+
+
+
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
, headers()
- .header("sample", "header"));
-
-// when:
- contractVerifierMessaging.send(inputMessage, "jms:input");
-
-// then:
- ContractVerifierMessage response = contractVerifierMessaging.receive("jms:output");
+ .header("sample", "header"));
+
+
+
+
+
contractVerifierMessaging.send(inputMessage, "jms:input");
+
+
+
+
+
ContractVerifierMessage response = contractVerifierMessaging.receive("jms:output");
assertThat(response).isNotNull();
assertThat(response.getHeader("BOOK-NAME")).isEqualTo("foo");
// and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
-'''
+'''
-
-
And the following Spock test would be created:
-
-
"""\
+And the following Spock test would be created:
+
+[source,groovy]
+
+
+
+
"""\
given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
'''{"bookName":"foo"}''',
['sample': 'header']
- )
-
-when:
- contractVerifierMessaging.send(inputMessage, 'jms:input')
-
-then:
+ )
+
+
+
when:
+ contractVerifierMessaging.send(inputMessage, 'jms:input')
+
+
+
then:
ContractVerifierMessage response = contractVerifierMessaging.receive('jms:output')
assert response !- null
response.getHeader('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
-"""
-
-
-
-
-
Scenario 3 (no output message)
-
-
For the given contract:
+"""
-
def contractDsl = Contract.make {
+===== Scenario 3 (no output message)
+
+For the given contract:
+
+[source,groovy]
+
+
+
+
def contractDsl = Contract.make {
label 'some_label'
input {
messageFrom('jms:delete')
@@ -4002,71 +3786,83 @@ and:
}
assertThat('bookWasDeleted()')
}
-}
-
-
-
-
The following JUnit test will be created:
+}
-
'''
-// given:
- ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
+The following JUnit test will be created:
+
+[source,groovy]
+
+
+
+
+
+
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
, headers()
- .header("sample", "header"));
-
-// when:
- contractVerifierMessaging.send(inputMessage, "jms:delete");
-
-// then:
- bookWasDeleted();
-'''
+ .header("sample", "header"));
-
-
And the following Spock test would be created:
+
+
+
contractVerifierMessaging.send(inputMessage, "jms:delete");
+
+
+
+
+
bookWasDeleted();
+'''
+
-
'''
-given:
+And the following Spock test would be created:
+
+[source,groovy]
+
+
+
+
+
given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
\'\'\'{"bookName":"foo"}\'\'\',
['sample': 'header']
- )
-
-when:
- contractVerifierMessaging.send(inputMessage, 'jms:delete')
-
-then:
+ )
+
+
+
when:
+ contractVerifierMessaging.send(inputMessage, 'jms:delete')
+
+
+
then:
noExceptionThrown()
bookWasDeleted()
-'''
+'''
-
-
-
-
-
Consumer Stub Side generation
-
-
Unlike the HTTP part - in Messaging we need to publish the Groovy DSL inside the JAR with a stub. Then it’s parsed on the consumer side
-and proper stubbed routes are created.
-
-
-
For more information please consult the Stub Runner Messaging sections.
-
-
-
Maven
+
-
<dependencies>
+==== Consumer Stub Side generation
+
+Unlike the HTTP part - in Messaging we need to publish the Groovy DSL inside the JAR with a stub. Then it's parsed on the consumer side
+and proper stubbed routes are created.
+
+For more information please consult the Stub Runner Messaging sections.
+
+[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
+.Maven
+
+
+
+
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
- </dependency>
-
- <dependency>
+ </dependency>
+
+
+
+
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<scope>test</scope>
@@ -4076,9 +3872,11 @@ and proper stubbed routes are created.
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
-</dependencies>
-
-<dependencyManagement>
+</dependencies>
+
+
+
+
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
@@ -4088,60 +3886,56 @@ and proper stubbed routes are created.
<scope>import</scope>
</dependency>
</dependencies>
-</dependencyManagement>
+</dependencyManagement>
-
-
-
Gradle
+
-
ext {
+[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
+.Gradle
+
+
+
+
ext {
contractsDir = file("mappings")
stubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
-}
-
-// Automatically added by plugin:
-// copyContracts - copies contracts to the output folder from which JAR will be created
-// verifierStubsJar - JAR with a provided stub suffix
-// the presented publication is also added by the plugin but you can modify it as you wish
-
-publishing {
+}
+
+
+
publishing {
publications {
stubs(MavenPublication) {
artifactId "${project.name}-stubs"
artifact verifierStubsJar
}
}
-}
+}
-
-
-
-
-
Spring Cloud Contract Stub Runner
-
-
One of the issues that you could have encountered while using Spring Cloud Contract Verifier was to pass the generated WireMock JSON stubs from the server side to the client side (or various clients).
- The same takes place in terms of client side generation for messaging.
-
-
-
Copying the JSON files / setting the client side for messaging manually is out of the question.
-
-
-
That’s why we’ll introduce Spring Cloud Contract Stub Runner that can download and run the stubs
-automatically for you.
-
-
-
Snapshot versions
-
-
Add the additional snapshot repository to your build.gradle to use snapshot versions which are automatically uploaded after every successful build:
-
-
-
Maven
+
-
<repositories>
+=== Spring Cloud Contract Stub Runner
+
+One of the issues that you could have encountered while using Spring Cloud Contract Verifier was to pass the generated WireMock JSON stubs from the server side to the client side (or various clients).
+ The same takes place in terms of client side generation for messaging.
+
+Copying the JSON files / setting the client side for messaging manually is out of the question.
+
+That's why we'll introduce Spring Cloud Contract Stub Runner that can download and run the stubs
+automatically for you.
+
+==== Snapshot versions
+
+Add the additional snapshot repository to your build.gradle to use snapshot versions which are automatically uploaded after every successful build:
+
+[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
+.Maven
+
+
+
+
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
- <url>https://repo.spring.io/snapshot</url>
+ <url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -4149,7 +3943,7 @@ automatically for you.
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
- <url>https://repo.spring.io/milestone</url>
+ <url>
https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -4157,7 +3951,7 @@ automatically for you.
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
- <url>https://repo.spring.io/release</url>
+ <url>
https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -4167,7 +3961,7 @@ automatically for you.
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
- <url>https://repo.spring.io/snapshot</url>
+ <url>
https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -4175,7 +3969,7 @@ automatically for you.
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
- <url>https://repo.spring.io/milestone</url>
+ <url>
https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -4183,53 +3977,48 @@ automatically for you.
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
- <url>https://repo.spring.io/release</url>
+ <url>
https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
-</pluginRepositories>
+</pluginRepositories>
-
-
-
Gradle
+
-
buildscript {
+[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
+.Gradle
+
+
+
+
buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/release" }
- }
+ }
-
-
-
-
Publishing stubs as JARs
-
-
The easiest approach would be to centralize the way stubs are kept. For example you can keep them as JARs in a Maven repository.
-
-
-
-
-|
- Tip
- |
-
-For both Maven and Gradle the setup comes out of the box. But you can customize it if you want to.
- |
-
-
-
-
-
Maven
+
-
<!-- First disable the default jar setup in the properties section-->
-<!-- we don't want the verifier to do a jar for us -->
-<spring.cloud.contract.verifier.skip>true</spring.cloud.contract.verifier.skip>
+==== Publishing stubs as JARs
-<!-- Next add the assembly plugin to your build -->
+The easiest approach would be to centralize the way stubs are kept. For example you can keep them as JARs in a Maven repository.
+
+TIP: For both Maven and Gradle the setup comes out of the box. But you can customize it if you want to.
+
+[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
+.Maven
+
+
+
+
<!-- First disable the default jar setup in the properties section-→
+<!-- we don’t want the verifier to do a jar for us -→
+<spring.cloud.contract.verifier.skip>true</spring.cloud.contract.verifier.skip>
+
+
+
<!-- Next add the assembly plugin to your build -→
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
@@ -4247,50 +4036,11 @@ For both Maven and Gradle the setup comes out of the box. But you can customize
</configuration>
</execution>
</executions>
-</plugin>
-
-<!-- Finally setup your assembly. Below you can find the contents of src/main/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>src/main/java</directory>
- <outputDirectory>/</outputDirectory>
- <includes>
- <include>**com/example/model/*.*</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>${project.build.directory}/classes</directory>
- <outputDirectory>/</outputDirectory>
- <includes>
- <include>**com/example/model/*.*</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>${project.build.directory}/snippets/stubs</directory>
- <outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings</outputDirectory>
- <includes>
- <include>**/*</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>${basedir}/src/test/resources/contracts</directory>
- <outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/contracts</outputDirectory>
- <includes>
- <include>**/*.groovy</include>
- </includes>
- </fileSet>
- </fileSets>
-</assembly>
+</plugin>
+
+
<!-- Finally setup your assembly. Below you can find the contents of src/main/assembly/stub.xml -→
+Unresolved directive in verifier/stubrunner.adoc - include::https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/master/producer_with_restdocs/src/assembly/stub.xml[indent=0]
Gradle
@@ -4316,6 +4066,7 @@ publishing {
+
Modules
@@ -5370,7 +5121,7 @@ Remember to annotate your test class with @AutoConfigureMessageVerifier
-
+
So as to trigger a message via the return_book_1 label we’ll use the StubTigger interface as follows
@@ -5399,7 +5150,7 @@ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
-
+
Since the route is set for you it’s enough to just send a message to the jms:output destination.
@@ -5569,7 +5320,7 @@ Remember to annotate your test class with
@AutoConfigureMessageVerifier
-
+
So as to trigger a message via the return_book_1 label we’ll use the StubTigger interface as follows
@@ -5598,7 +5349,7 @@ receivedMessage.headers.get('BOOK-NAME') == 'foo'
-
+
Since the route is set for you it’s enough to just send a message to the output destination.
@@ -5771,7 +5522,7 @@ debug: true
-
+
So as to trigger a message via the return_book_1 label we’ll use the StubTrigger interface as follows
@@ -5800,7 +5551,7 @@ receivedMessage.headers.get('BOOK-NAME') == 'foo'
-
+
Since the route is set for you it’s enough to just send a message to the bookStorage destination.