Merge branch '1.1.x'

This commit is contained in:
Marcin Grzejszczak
2017-08-30 16:40:04 +02:00
13 changed files with 522 additions and 1092 deletions

View File

@@ -20,7 +20,7 @@ http://cloud-samples.spring.io/spring-cloud-contract-samples/workshops.html[this
=== Spring Cloud Contract Verifier
=== Introduction
== Spring Cloud Contract Verifier Introduction
TIP: The Accurest project was initially started by Marcin Grzejszczak and Jakub Kubrynski (http://codearte.io[codearte.io])
@@ -35,13 +35,13 @@ Full test is generated by Spring Cloud Contract Verifier.
Spring Cloud Contract Verifier moves TDD to the level of software architecture.
==== Why?
=== Why?
Let us assume that we have a system comprising of multiple microservices:
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Deps.png[Microservices Architecture]
===== Testing issues
==== Testing issues
If we wanted to test the application in top left corner if it can communicate with other services then we could do one of two things:
@@ -85,7 +85,7 @@ image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{bra
Spring Cloud Contract Verifier gives you the certainty that the stubs that you're using were created by the service that you're calling. Also if you can use them it means that they were
tested against the producer's side. In other words - you can trust those stubs.
==== Purposes
=== Purposes
The main purposes of Spring Cloud Contract Verifier with Stub Runner are:
@@ -99,9 +99,9 @@ Let's assume that we have a business use case of fraud check. If a user can be a
we would assume that you would create 2 contracts. One for the positive and one for the negative fraud case.
Contract tests are used to test contracts between applications and not to simulate full behaviour.
==== How
=== How
===== Define the contract
==== Define the contract
As consumers we need to define what exactly we want to achieve. We need to formulate our expectations. That's why we write the following contract.
@@ -168,7 +168,7 @@ From the Producer perspective, in the autogenerated producer-side test:
*/
----
===== Client Side
==== Client Side
Spring Cloud Contract will generate stubs, which you can use during client side testing.
You will have a WireMock instance / Messaging route up and running that simulates the service Y.
@@ -197,7 +197,7 @@ public class LoanApplicationServiceTests {
After that, during the tests Spring Cloud Contract will automatically find the stubs (simulating the real service) in Maven repository and expose them on configured (or random) port.
===== Server Side
==== Server Side
Being a service Y since you are developing your stub, you need to be sure that it's actually resembling your
concrete implementation. You can't have a situation where your stub acts in one way and your application on
@@ -231,7 +231,7 @@ public void validate_shouldMarkClientAsFraud() throws Exception {
}
----
==== Step by step guide to CDC
=== Step by step guide to CDC
Let's take an example of Fraud Detection and Loan Issuance process. The business scenario is such that we want to issue loans to people but don't want them to steal the money from us. The current implementation of our system grants loans to everybody.
@@ -248,7 +248,7 @@ The https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples/
TIP: In this case the ownership of the contracts lays on the producer side. It means that physically
all the contract are present in the producer's repository
===== Technical note
==== Technical note
If using the *SNAPSHOT* / *Milestone* / *Release Candidate* versions please add the following section to your
@@ -321,7 +321,7 @@ repositories {
}
----
===== Consumer side (Loan Issuance)
==== Consumer side (Loan Issuance)
As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):
@@ -601,7 +601,7 @@ What we did until now is an iterative process. We can play around with the contr
Once we're satisfied with the results and the test passes publish a PR to the server side. Currently the consumer side work is done.
===== Producer side (Fraud Detection server)
==== Producer side (Fraud Detection server)
As a developer of the Fraud Detection server (a server to the Loan Issuance service):
@@ -762,7 +762,7 @@ git push origin master
Then we assume that your CI would run sth like `./mvnw clean deploy` which would publish both the application and the stub artifcats.
===== Consumer side (Loan Issuance) final step
==== Consumer side (Loan Issuance) final step
As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):
@@ -789,599 +789,36 @@ stubrunner:
And that's it!
==== Dependencies
=== Dependencies
The best way to add the dependencies is to just use the proper `starter` dependency.
For `stub-runner` use `spring-cloud-starter-stub-runner` and when you're using a plugin just add
`spring-cloud-starter-contract-verifier`.
==== Additional links
=== Additional links
Below you can find some resources related to Spring Cloud Contract Verifier and Stub Runner. Note that some can be outdated since the Spring Cloud Contract Verifier project
is under constant development.
===== Spring Cloud Contract video
==== Spring Cloud Contract video
You can check out the video from the Warsaw JUG about Spring Cloud Contract:
video::sAAklvxmPmk[youtube,start=538,width=640,height=480]
===== Readings
==== Readings
- http://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura[Slides from Marcin Grzejszczak's talk about Accurest]
- http://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog]
- http://toomuchcoding.com/blog/categories/spring-cloud-contract/[Spring Cloud Contract related articles from Marcin Grzejszczak's blog]
- http://groovy-lang.org/json.html[Groovy docs regarding JSON]
==== Samples
=== Samples
Here you can find some https://github.com/spring-cloud-samples/spring-cloud-contract-samples[samples].
=== FAQ
==== Why use Spring Cloud Contract Verifier and not X ?
For the time being Spring Cloud Contract Verifier is a JVM based tool. So it could be your first pick when you're already creating
software for the JVM. This project has a lot of really interesting features but especially quite a few of them definitely make
Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Contract (CDC) tooling. Out of many the most interesting are:
- Possibility to do CDC with messaging
- Clear and easy to use, statically typed DSL
- Possibility to copy paste your current JSON file to the contract and only edit its elements
- Automatic generation of tests from the defined Contract
- Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory
- Spring Cloud integration - no discovery service is needed for integration tests
==== What is this value(consumer(), producer()) ?
One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
What typically makes that difficult are the hard-coded values of request / response elements. For example dates or ids.
Imagine the following JSON request
[source,json,indent=0]
----
{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}
----
and JSON response
[source,json,indent=0]
----
{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}
----
Imagine the pain required to set proper value of the `time` field (let's assume that this content is generated by the
database) by changing the clock in the system or providing stub implementations of data providers. The same is related
to the field called `id`. Will you create a stubbed implementation of UUID generator? Makes little sense...
So as a consumer you would like to send a request that matches any form of a time or any UUID. That way your system
will work as usual - will generate data and you won't have to stub anything out. Let's assume that in case of the aforementioned
JSON the most important part is the `body` field. You can focus on that and provide matching for other fields. In other words
you would like the stub to work like this:
[source,json,indent=0]
----
{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "foo"
}
----
As far as the response goes as a consumer you need a concrete value that you can operate on. So such a JSON is valid
[source,json,indent=0]
----
{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}
----
As you could see in the previous sections we generate tests from contracts. So from the producer's side the situation looks
much different. We're parsing the provided contract and in the test we want to send a real request to your endpoints.
So for the case of a producer for the request we can't have any sort of matching. We need concrete values that the
producer's backend can work on. Such a JSON would be a valid one:
[source,json,indent=0]
----
{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}
----
On the other hand from the point of view of the validity of the contract the response doesn't necessarily have to
contain concrete values of `time` or `id`. Let's say that you generate those on the producer side - again, you'd
have to do a lot of stubbing to ensure that you always return the same values. That's why from the producer's side
what you might want is the following response:
[source,json,indent=0]
----
{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "bar"
}
----
How can you then provide one time a matcher for the consumer and a concrete value for the producer and vice versa?
In Spring Cloud Contract we're allowing you to provide a *dynamic value*. That means that it can differ for both
sides of the communication. You can pass the values:
Either via the `value` method
[source,groovy,indent=0]
----
value(consumer(...), producer(...))
value(stub(...), test(...))
value(client(...), server(...))
----
or using the `$()` method
[source,groovy,indent=0]
----
$(consumer(...), producer(...))
$(stub(...), test(...))
$(client(...), server(...))
----
You can read more about this in the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl[Contract DSL section].
Calling `value()` or `$()` tells Spring Cloud Contract that you will be passing a dynamic value.
Inside the `consumer()` method you pass the value that should be used on the consumer side (in the generated stub).
Inside the `producer()` method you pass the value that should be used on the producer side (in the generated test).
TIP: If on one side you have passed the regular expression and you haven't passed the other, then the
other side will get auto-generated.
Most often you will use that method together with the `regex` helper method. E.g. `consumer(regex('[0-9]{10}'))`.
To sum it up the contract for the aforementioned scenario would look more or less like this (the regular expression
for time and UUID are simplified and most likely invalid but we want to keep things very simple in this example):
[source,groovy,indent=0]
----
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/someUrl'
body([
time : value(consumer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value(consumer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "foo"
])
}
response {
status 200
body([
time : value(producer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value([producer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "bar"
])
}
}
----
IMPORTANT: Please read the http://groovy-lang.org/json.html[Groovy docs related to JSON] to understand how to
properly structure the request / response bodies.
==== How to do Stubs versioning?
===== API Versioning
Let's try to answer a question what versioning really means. If you're referring to the API version then there are
different approaches.
- use Hypermedia, links and do not version your API by any means
- pass versions through headers / urls
I will not try to answer a question which approach is better. Whatever suit your needs and allows you to generate
business value should be picked.
Let's assume that you do version your API. In that case you should provide as many contracts as many versions you support.
You can create a subfolder for every version or append it to th contract name - whatever suits you more.
===== JAR versioning
If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.
Let's assume that you're doing Continuous Delivery / Deployment which means that you're generating a new version of
the jar each time you go through the pipeline and that jar can go to production at any time. For example your jar version
looks like this (it got built on the 20.10.2016 at 20:15:21) :
[source,groovy,indent=0]
----
1.0.0.20161020-201521-RELEASE
----
In that case your generated stub jar will look like this.
[source,groovy,indent=0]
----
1.0.0.20161020-201521-RELEASE-stubs.jar
----
In this case you should inside your `application.yml` or `@AutoConfigureStubRunner` when referencing stubs provide the
latest version of the stubs. You can do that by passing the `+` sign. Example
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
----
If the versioning however is fixed (e.g. `1.0.4.RELEASE` or `2.1.1`) then you have to set the concrete value of the jar
version. Example for 2.1.1.
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:2.1.1:stubs:8080"})
----
===== Dev or prod stubs
You can manipulate the classifier to run the tests against current development version of the stubs of other services
or the ones that were deployed to production. If you alter your build to deploy the stubs with the `prod-stubs` classifier
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.
Example of tests using development version of stubs
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
----
Example of tests using production version of stubs
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:prod-stubs:8080"})
----
You can pass those values also via properties from your deployment pipeline.
==== Common repo with contracts
Another way of storing contracts other than having them with the producer is keeping them in a common place.
It can be related to security issues where the consumers can't clone the producer's code. Also if you keep
contracts in a single place then you, as a producer, will know how many consumers you have and which
consumer will you break with your local changes.
===== Repo structure
Let's assume that we have a producer with coordinates `com.example:server` and 3 consumers: `client1`,
`client2`, `client3`. Then in the repository with common contracts you would have the following setup
(which you can checkout https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples/standalone/contracts[here]:
[source,bash,indent=0]
----
├── com
│   └── example
│   └── server
│   ├── client1
│   │   └── expectation.groovy
│   ├── client2
│   │   └── expectation.groovy
│   ├── client3
│   │   └── expectation.groovy
│   └── pom.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
└── assembly
└── contracts.xml
----
As you can see the under the slash-delimited groupid `/` artifact id folder (`com/example/server`) you have
expectations of the 3 consumers (`client1`, `client2` and `client3`). Expectations are the standard Groovy DSL
contract files as described throughout this documentation. This repository has to produce a JAR file that maps
one to one to the contents of the repo.
Example of a `pom.xml` inside the `server` folder.
[source,xml,indent=0]
----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Server Stubs</name>
<description>POM used to install locally stubs for consumer side</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring-cloud-contract.version>1.2.0.BUILD-SNAPSHOT</spring-cloud-contract.version>
<spring-cloud-dependencies.version>Edgware.BUILD-SNAPSHOT</spring-cloud-dependencies.version>
<excludeBuildFolders>true</excludeBuildFolders>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- By default it would search under src/test/resources/ -->
<contractsDirectory>${project.basedir}</contractsDirectory>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
----
As you can see there are no dependencies other than the Spring Cloud Contract Maven Plugin.
Those poms are necessary for the consumer side to run `mvn clean install -DskipTests` to locally install
stubs of the producer project.
The `pom.xml` in the root folder can look like this:
[source,xml,indent=0]
----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.standalone</groupId>
<artifactId>contracts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Contracts</name>
<description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the producers to generate tests and stubs</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>contracts</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<attach>true</attach>
<descriptor>${basedir}/src/assembly/contracts.xml</descriptor>
<!-- If you want an explicit classifier remove the following line -->
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
----
It's using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:
[source,xml,indent=0]
----
<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>
----
===== 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]
----
<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>
<contractDependency>
<groupId>com.example.standalone</groupId>
<artifactId>contracts</artifactId>
</contractDependency>
</configuration>
</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?
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.
==== How can I debug the request/response being sent by the generated tests client?
The generated tests all boil down to RestAssured in some form or fashion which relies on https://hc.apache.org/httpcomponents-client-ga/[Apache HttpClient]. HttpClient has a facility called https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging[wire logging] which logs the entire request and response to HttpClient. Spring Boot has a logging https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html[common application property] for doing this sort of thing, just add this to your application properties
[source,properties,indent=0]
----
logging.level.org.apache.http.wire=DEBUG
----
==== How can I debug the mapping/request/response being sent by WireMock?
Starting from version `1.2.0` we turn on WireMock logging to
info and the WireMock notifier to being verbose. Now you will
exactly know what request was received by WireMock server and which
matching response definition was picked.
To turn off this feature just bump WireMock logging to `ERROR`
[source,properties,indent=0]
----
logging.level.com.github.tomakehurst.wiremock=ERROR
----
==== How can I see what got registered in the HTTP server stub?
You can use the `mappingsOutputFolder` property on `@AutoConfigureStubRunner` or `StubRunnerRule`
to dump all mappings per artifact id. Also the port at which the given stub server was
started will be attached.
==== Can I reference the request from the response?
Yes! With version 1.1.0 we've added such a possibility. On the HTTP stub server side we're providing support
for this for WireMock. In case of other HTTP server stubs you'll have to implement the approach yourself.
==== Can I reference text from file?
Yes! With version 1.2.0 we've added such a possibility. It's enough to call `file(...)` method in the
DSL and provide a path relative to where the contract lays.
=== Links
Here you can find interesting links related to Spring Cloud Contract Verifier:
- https://github.com/spring-cloud/spring-cloud-contract/[Spring Cloud Contract Github Repository]
- https://github.com/spring-cloud-samples/spring-cloud-contract-samples/[Spring Cloud Contract Samples]
- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html[Spring Cloud Contract Documentation]
- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/deprecated[Accurest Legacy Documentation]
- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#spring-cloud-contract-stub-runner[Spring Cloud Contract Stub Runner Documentation]
- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#stub-runner-for-messaging[Spring Cloud Contract Stub Runner Messaging Documentation]
- https://gitter.im/spring-cloud/spring-cloud-contract[Spring Cloud Contract Gitter]
- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/[Spring Cloud Contract Maven Plugin]
- https://www.youtube.com/watch?v=sAAklvxmPmk[Spring Cloud Contract WJUG Presentation by Marcin Grzejszczak]
Unresolved directive in README.adoc - include::verifier_links.adoc[]
=== Spring Cloud Contract WireMock
@@ -1389,18 +826,13 @@ Here you can find interesting links related to Spring Cloud Contract Verifier:
:doc_samples: {core_path}/samples/wiremock-jetty
:wiremock_tests: {core_path}/spring-cloud-contract-wiremock
== Spring Cloud Contract WireMock
Modules giving you the possibility to use
http://wiremock.org[WireMock] with different servers by using the
"ambient" server embedded in a Spring Boot application. Check out the
http://wiremock.org[WireMock] in a Spring Boot application. Check out the
https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples[samples]
for more details.
IMPORTANT: The Spring Cloud Release Train BOM imports `spring-cloud-contract-dependencies`
which in turn has exclusions for the dependencies needed by WireMock. This might lead to a situation that
even if you're not using Spring Cloud Contract then your dependencies will be influenced
anyways.
If you have a Spring Boot application that uses Tomcat as an embedded
server, for example (the default with `spring-boot-starter-web`), then
you can simply add `spring-cloud-contract-wiremock` to your classpath
@@ -1519,7 +951,7 @@ public class WiremockForDocsClassRuleTests {
The use `@ClassRule` means that the server will shut down after all the methods in this class.
== Relaxed SSL Validation for Rest Template
=== Relaxed SSL Validation for Rest Template
WireMock allows you to stub a "secure" server with an "https" URL protocol. If your application wants to
contact that stub server in an integration test, then it will find that the SSL certificates are not
@@ -1562,7 +994,7 @@ be selected by the `RestTemplateBuilder` and configured to ignore SSL errors. If
client you don't need the annotation (but it won't do any harm). There is no support currently for other clients, but
it may be added in future releases.
== WireMock and Spring MVC Mocks
=== WireMock and Spring MVC Mocks
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a
Spring `MockRestServiceServer`. Here's an example:
@@ -1609,7 +1041,7 @@ particular version of Jetty (currently 9.2). To use the native Jetty
you need to add the native wiremock dependencies and exclude the
Spring Boot container if there is one.
== Generating Stubs using RestDocs
=== Generating Stubs using RestDocs
https://projects.spring.io/spring-restdocs[Spring RestDocs] can be
used to generate documentation (e.g. in asciidoctor format) for an
@@ -1739,7 +1171,7 @@ After that, you can create a stub using WireMock in a
number of different ways, including as described above using
`@AutoConfigureWireMock(stubs="classpath:resource.json")`.
== Generating Contracts using RestDocs
=== Generating Contracts using RestDocs
Another thing that can be generated with Spring RestDocs is the Spring Cloud
Contract DSL file and documentation. If you combine that with Spring Cloud

View File

@@ -1,4 +1,4 @@
=== Links
== Links
Here you can find interesting links related to Spring Cloud Contract Verifier:

View File

@@ -2,6 +2,8 @@
:doc_samples: {core_path}/samples/wiremock-jetty
:wiremock_tests: {core_path}/spring-cloud-contract-wiremock
== Migrations
In the following document we will write about necessary migration steps between versions.
=== 1.0.x -> 1.1.x

View File

@@ -15,7 +15,7 @@
include::verifier_introduction.adoc[]
include::verifier_rest.adoc[]
include::verifier_setup.adoc[]
include::verifier_messaging.adoc[]
@@ -23,6 +23,4 @@ include::verifier_stubrunner.adoc[]
include::verifier_stubrunner_msg.adoc[]
include::verifier_contract.adoc[]
include::verifier_links.adoc[]
include::verifier_contract.adoc[]

View File

@@ -21,14 +21,10 @@ This project provides support for Consumer Driven Contracts and service schemas
range of options for writing tests, publishing them as assets, asserting that a contract is kept by producers
and consumers, for HTTP and message-based interactions.
== Spring Cloud Contract Verifier
include::spring-cloud-contract-verifier.adoc[]
== Spring Cloud Contract WireMock
include::spring-cloud-wiremock.adoc[]
== Migrations
include::migrations.adoc[]
include::migrations.adoc[]
include::links.adoc[]

View File

@@ -2,6 +2,7 @@
:doc_samples: {core_path}/samples/wiremock-jetty
:wiremock_tests: {core_path}/spring-cloud-contract-wiremock
== Spring Cloud Contract WireMock
Modules giving you the possibility to use
http://wiremock.org[WireMock] in a Spring Boot application. Check out the
@@ -88,7 +89,7 @@ include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.j
The use `@ClassRule` means that the server will shut down after all the methods in this class.
== Relaxed SSL Validation for Rest Template
=== Relaxed SSL Validation for Rest Template
WireMock allows you to stub a "secure" server with an "https" URL protocol. If your application wants to
contact that stub server in an integration test, then it will find that the SSL certificates are not
@@ -131,7 +132,7 @@ be selected by the `RestTemplateBuilder` and configured to ignore SSL errors. If
client you don't need the annotation (but it won't do any harm). There is no support currently for other clients, but
it may be added in future releases.
== WireMock and Spring MVC Mocks
=== WireMock and Spring MVC Mocks
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a
Spring `MockRestServiceServer`. Here's an example:
@@ -158,7 +159,7 @@ particular version of Jetty (currently 9.2). To use the native Jetty
you need to add the native wiremock dependencies and exclude the
Spring Boot container if there is one.
== Generating Stubs using RestDocs
=== Generating Stubs using RestDocs
https://projects.spring.io/spring-restdocs[Spring RestDocs] can be
used to generate documentation (e.g. in asciidoctor format) for an
@@ -288,7 +289,7 @@ After that, you can create a stub using WireMock in a
number of different ways, including as described above using
`@AutoConfigureWireMock(stubs="classpath:resource.json")`.
== Generating Contracts using RestDocs
=== Generating Contracts using RestDocs
Another thing that can be generated with Spring RestDocs is the Spring Cloud
Contract DSL file and documentation. If you combine that with Spring Cloud

View File

@@ -1,4 +1,4 @@
=== Contract DSL
== Contract DSL
IMPORTANT: Remember that inside the contract file you have to provide the fully qualified name to
the `Contract` class and the `make` static import i.e. `org.springframework.cloud.spec.Contract.make { ... }`.
@@ -24,7 +24,7 @@ Not all features of the DSL are used in example above. If you didn't find what y
> You can easily compile Contracts to WireMock stubs mapping using standalone maven command: `mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:convert`.
==== Limitations
=== Limitations
WARNING: Spring Cloud Contract Verifier doesn't support XML properly. Please use JSON or help us implement this feature.
@@ -36,9 +36,9 @@ WARNING: Due to the fact that JSON structure can have any form it's sometimes im
the `value(consumer(...), producer(...))` notation when using that in GString. That's why we highly recommend using the
Groovy Map notation.
==== Common Top-Level elements
=== Common Top-Level elements
===== Description
==== Description
You can add a `description` to your contract that is nothing else but an arbitrary text. Example:
@@ -47,7 +47,7 @@ You can add a `description` to your contract that is nothing else but an arbitra
include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=description,indent=0]
----
===== Name
==== Name
You can provide a name of your contract. Let's assume that you've provided a name `should register a user`.
If you do this then the name of the autogenerated test will be equal to `validate_should_register_a_user`.
@@ -57,7 +57,7 @@ IMPORTANT: Please ensure that the name doesn't contain any characters that will
not possible to compile. Also remember that if you provide the same name for multiple contracts then your
autogenerated tests will fail to compile and your generated stubs will override each other.
===== Ignoring contracts
==== Ignoring contracts
If you want to ignore a contract you can either set a value of ignored contracts in the plugin configuration
or just set the `ignored` property on the contract itself:
@@ -67,7 +67,7 @@ or just set the `ignored` property on the contract itself:
include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=ignored,indent=0]
----
===== Passing values from files
==== Passing values from files
Starting with version `1.2.0` it's possible to pass values from files. Let's assume that we have
the following resources in our project.
@@ -118,7 +118,7 @@ Following methods can be called in the top-level closure of a contract definitio
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=http_dsl,indent=0]
----
==== Request
=== Request
HTTP protocol requires only **method and address** to be specified in a request. The same information is mandatory in request definition of the Contract.
@@ -196,7 +196,7 @@ The WireMock stub will look more or less like this:
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy[tags=multipartwiremock,indent=0]
----
==== Response
=== Response
Minimal response must contain **HTTP status code**.
@@ -207,14 +207,14 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
Besides status response may contain **headers** and **body**, which are specified the same way as in the request (see previous paragraph).
==== Dynamic properties
=== Dynamic properties
The contract can contain some dynamic properties - timestamps / ids etc. You don't want to enforce the consumers to stub their
clocks to always return the same value of time so that it gets matched by the stub. That's why we allow you to provide the dynamic
parts in your contracts in two ways. One is to pass them directly in the
body and one to set them in a separate section called `testMatchers` and `stubMatchers`.
===== Dynamic properties inside the body
==== Dynamic properties inside the body
You can set the properties inside the body either via the `value` method
@@ -239,7 +239,7 @@ $(client(...), server(...))
All of the aforementioned approaches are equal. That means that `stub` and `client` methods are aliases over the `consumer`
method. Let's take a closer look at what we can do with those values in the subsequent sections.
====== Regular expressions
==== Regular expressions
You can use regular expressions to write your requests in Contract DSL. It is particularly useful when you want to indicate that a given response
should be provided for requests that follow a given pattern. Also, you can use it when you need to use patterns and not exact values both
@@ -276,7 +276,7 @@ so in your contract you can use it like this
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy[tags=contract_with_regex,indent=0]
----
====== Passing optional parameters
==== Passing optional parameters
It is possible to provide optional parameters in your contract. It's only possible to have optional parameter for the:
@@ -306,7 +306,7 @@ and the following stub:
include::{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy[tags=wiremock,indent=0]
----
====== Executing custom methods on server side
==== Executing custom methods on server side
It is also possible to define a method call to be executed on the server side during the test. Such a method can be added to the class defined as "baseClassForTests"
in the configuration. Example:
@@ -369,7 +369,7 @@ It would more or less like this:
assertThat(response.statusCode()).isEqualTo(200);
----
===== Referencing request from response
==== Referencing request from response
The best situation is to provide fixed values but sometimes you need to reference a request in your response.
In order to do this you can profit from the `fromRequest()` method that allows you to reference a bunch
@@ -483,7 +483,7 @@ proper values. Additionally we're registering 2 helper functions. `escapejsonbod
body in a format that can be embedded in a JSON. Another is `jsonpath` that for a given parameter knows how to
find an object in the request body.
===== Dynamic properties in matchers sections
==== Dynamic properties in matchers sections
If you've been working with https://docs.pact.io/[Pact] this might seem familiar. Quite a few users
are used to having a separation between the body and setting dynamic parts of your contract.
@@ -671,7 +671,7 @@ As you can see the assertion is malformed. That's because only the first element
In order to fix this it's best to apply the assertion to the whole `$.events` collection and assert it
via the `byCommand(...)` method.
==== JAX-RS support
=== JAX-RS support
We support JAX-RS 2 Client API. Base class needs to define `protected WebTarget webTarget` and server initialization, right now the only option how to test JAX-RS API is to start a web server.
@@ -681,7 +681,7 @@ In order to use JAX-RS mode, use the following settings:
[source,groovy,indent=0]
----
testMode === 'JAXRSCLIENT'
testMode == 'JAXRSCLIENT'
----
Example of a test API generated:
@@ -691,7 +691,7 @@ Example of a test API generated:
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy[tags=jaxrs,indent=0]
----
==== Async support
=== Async support
If you're using asynchronous communication on the server side (your controllers are returning
`Callable`, `DeferredResult` etc. then inside your contract you have to provide in the `response`
@@ -712,7 +712,7 @@ org.springframework.cloud.contract.spec.Contract.make {
}
----
==== Working with Context Paths
=== Working with Context Paths
Spring Cloud Contract supports context paths.
@@ -766,11 +766,11 @@ That way all:
- your contracts reflect that you have a context path, thus your generated stubs will also
have that information (e.g. in the stubs you'll see that you have too call `/my-context-path/url`)
==== Messaging Top-Level Elements
=== Messaging Top-Level Elements
The DSL for messaging looks a little bit different than the one that focuses on HTTP.
===== Output triggered by a method
==== Output triggered by a method
The output message can be triggered by calling a method (e.g. a Scheduler was started and a message was sent)
@@ -782,7 +782,7 @@ include::{tests_path}/samples-messaging-integration/src/test/groovy/com/example/
In this case the output message will be sent to `output` if a method called `bookReturnedTriggered` will be executed. In the message *publisher's* side
we will generate a test that will call that method to trigger the message. On the *consumer* side you can use the `some_label` to trigger the message.
===== Output triggered by a message
==== Output triggered by a message
The output message can be triggered by receiving a message.
@@ -795,7 +795,7 @@ In this case the output message will be sent to `output` if a proper message wil
we will generate a test that will send the input message to the defined destination. On the *consumer* side you can either send a message to the input
destination or use the `some_label` to trigger the message.
===== Consumer / Producer
==== Consumer / Producer
In HTTP you have a notion of `client`/`stub and `server`/`test` notation. You can use them also in messaging but we're providing also the `consumer` and `produer` methods
as presented below (note you can use either `$` or `value` methods to provide `consumer` and `producer` parts)
@@ -805,7 +805,7 @@ as presented below (note you can use either `$` or `value` methods to provide `c
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=consumer_producer]
----
==== Multiple contracts in one file
=== Multiple contracts in one file
It's possible to define multiple contracts in one file. An example of such a contract can look like this
@@ -884,9 +884,9 @@ TIP: As you can see it's much better if you name your contracts since then your
are far more meaningful.
=== Customization
== Customization
==== Extending the DSL
=== Extending the DSL
It is possible to provide your own functions to the DSL. The key requirement for this
feature was to maintain the static compatibility. Below you will be able to see an example
@@ -897,7 +897,7 @@ of:
The full example can be found https://github.com/spring-cloud-samples/spring-cloud-contract-samples[here].
===== Common JAR
==== Common JAR
Below you can find three classes that we will reuse in the DSLs.
@@ -922,12 +922,12 @@ include::{samples_url}/common/src/main/java/com/example/ConsumerUtils.java[]
include::{samples_url}/common/src/main/java/com/example/ProducerUtils.java[]
----
===== Adding the dependency to project
==== Adding the dependency to project
In order for the plugins and IDE to be able to reference the common JAR classes you need
to pass the dependency to your project.
====== Test dependency in project's dependencies
==== Test dependency in project's dependencies
First add the common jar dependency as a test dependency. That way since your
contracts files are available at test resources path, automatically the
@@ -945,7 +945,7 @@ include::{samples_url}/producer/pom.xml[tags=test_dep,indent=0]
include::{samples_url}/producer/build.gradle[tags=test_dep,indent=0]
----
====== Test dependency in plugin's dependencies
==== Test dependency in plugin's dependencies
Now you have to add the dependency for the plugin to reuse at runtime.
@@ -961,7 +961,7 @@ include::{samples_url}/producer/pom.xml[tags=test_dep_in_plugin,indent=0]
include::{samples_url}/producer/build.gradle[tags=test_dep_in_plugin,indent=0]
----
====== Referencing classes in DSLs
==== Referencing classes in DSLs
Now you can reference your classes in your DSL. Example:
@@ -970,7 +970,7 @@ Now you can reference your classes in your DSL. Example:
include::{samples_url}/producer/src/test/resources/contracts/beer/rest/shouldGrantABeerIfOldEnough.groovy[indent=0]
----
=== Pluggable architecture
== Pluggable architecture
There are cases where you have your contracts defined in other formats
like YAML, RAML or PACT. On the other hand you'd like to profit from
@@ -979,7 +979,7 @@ of either of those. Also you can customize the way tests are generated (for exam
tests for other languages) and you can do the same for stubs generation (you can generate
stubs for other stub http server implementations).
==== Custom contract converter
=== Custom contract converter
Let's assume that your contract is written in a YAML file like this:
@@ -1016,13 +1016,13 @@ and the YAML implementation
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy[indent=0,lines=16..-1]
----
===== Pact converter
==== Pact converter
Spring Cloud Contract comes with an out of the box support for https://docs.pact.io/[Pact] representation of contracts.
In other words instead of using the Groovy DSL you can use Pact files. In this section
we will present how to add such a support for your project.
====== Pact contract
==== Pact contract
We will be working on the following example of a Pact contract. We've placed this file under
the `src/test/resources/contracts` folder.
@@ -1032,7 +1032,7 @@ the `src/test/resources/contracts` folder.
include::{standalone_pact_path}/pact-http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.json[indent=0]
----
====== Pact for producers
==== Pact for producers
On the producer side you have add to your plugin configuration two additional dependencies.
One is the Spring Cloud Contract Pact support and the other represents the current
@@ -1106,7 +1106,7 @@ and the stub looking like this
}
----
====== Pact for consumers
==== Pact for consumers
On the producer side you have add to your project dependencies two additional dependencies.
One is the Spring Cloud Contract Pact support and the other represents the current
@@ -1124,7 +1124,7 @@ include::{standalone_pact_path}/pact-http-client/pom.xml[tags=pact_dependency,in
include::{standalone_pact_path}/pact-http-client/build.gradle[tags=pact_dependency,indent=0]
----
==== Custom test generator
=== Custom test generator
If you want to generate tests for different languages than Java or you're
not happy with the way we're building Java tests for you then you can register
@@ -1146,7 +1146,7 @@ org.springframework.cloud.contract.verifier.builder.SingleTestGenerator=/
com.example.MyGenerator
----
==== Custom stub generator
=== Custom stub generator
If you want to generate stubs for other stub server than WireMock it's enough to
plug in your own implementation of this interface:
@@ -1169,7 +1169,7 @@ The default implementation is the WireMock stub generation.
TIP: You can provide multiple stub generator implementations. That way for example from a single
DSL as input you can e.g. produce WireMock stubs and Pact files too!
==== Custom Stub Runner
=== Custom Stub Runner
If you decide to have a custom stub generation you also need a custom way of running
stubs with your different stub provider.
@@ -1198,7 +1198,7 @@ that way you'll be able to run stubs using Moco.
IMPORTANT: If you don't provide any implementation then the default one - WireMock based
will be picked. If you provide more than one then the first one on the list will be picked.
==== Custom Stub Downloader
=== Custom Stub Downloader
You can customize the way your stubs are downloaded. It's enough to create an
implementation of the `StubDownloaderBuilder`

View File

@@ -0,0 +1,373 @@
:introduction_url: https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master
== Spring Cloud Contract FAQ
=== Why use Spring Cloud Contract Verifier and not X ?
For the time being Spring Cloud Contract Verifier is a JVM based tool. So it could be your first pick when you're already creating
software for the JVM. This project has a lot of really interesting features but especially quite a few of them definitely make
Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Contract (CDC) tooling. Out of many the most interesting are:
- Possibility to do CDC with messaging
- Clear and easy to use, statically typed DSL
- Possibility to copy paste your current JSON file to the contract and only edit its elements
- Automatic generation of tests from the defined Contract
- Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory
- Spring Cloud integration - no discovery service is needed for integration tests
=== What is this value(consumer(), producer()) ?
One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
What typically makes that difficult are the hard-coded values of request / response elements. For example dates or ids.
Imagine the following JSON request
[source,json,indent=0]
----
{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}
----
and JSON response
[source,json,indent=0]
----
{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}
----
Imagine the pain required to set proper value of the `time` field (let's assume that this content is generated by the
database) by changing the clock in the system or providing stub implementations of data providers. The same is related
to the field called `id`. Will you create a stubbed implementation of UUID generator? Makes little sense...
So as a consumer you would like to send a request that matches any form of a time or any UUID. That way your system
will work as usual - will generate data and you won't have to stub anything out. Let's assume that in case of the aforementioned
JSON the most important part is the `body` field. You can focus on that and provide matching for other fields. In other words
you would like the stub to work like this:
[source,json,indent=0]
----
{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "foo"
}
----
As far as the response goes as a consumer you need a concrete value that you can operate on. So such a JSON is valid
[source,json,indent=0]
----
{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}
----
As you could see in the previous sections we generate tests from contracts. So from the producer's side the situation looks
much different. We're parsing the provided contract and in the test we want to send a real request to your endpoints.
So for the case of a producer for the request we can't have any sort of matching. We need concrete values that the
producer's backend can work on. Such a JSON would be a valid one:
[source,json,indent=0]
----
{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}
----
On the other hand from the point of view of the validity of the contract the response doesn't necessarily have to
contain concrete values of `time` or `id`. Let's say that you generate those on the producer side - again, you'd
have to do a lot of stubbing to ensure that you always return the same values. That's why from the producer's side
what you might want is the following response:
[source,json,indent=0]
----
{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "bar"
}
----
How can you then provide one time a matcher for the consumer and a concrete value for the producer and vice versa?
In Spring Cloud Contract we're allowing you to provide a *dynamic value*. That means that it can differ for both
sides of the communication. You can pass the values:
Either via the `value` method
[source,groovy,indent=0]
----
value(consumer(...), producer(...))
value(stub(...), test(...))
value(client(...), server(...))
----
or using the `$()` method
[source,groovy,indent=0]
----
$(consumer(...), producer(...))
$(stub(...), test(...))
$(client(...), server(...))
----
You can read more about this in the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl[Contract DSL section].
Calling `value()` or `$()` tells Spring Cloud Contract that you will be passing a dynamic value.
Inside the `consumer()` method you pass the value that should be used on the consumer side (in the generated stub).
Inside the `producer()` method you pass the value that should be used on the producer side (in the generated test).
TIP: If on one side you have passed the regular expression and you haven't passed the other, then the
other side will get auto-generated.
Most often you will use that method together with the `regex` helper method. E.g. `consumer(regex('[0-9]{10}'))`.
To sum it up the contract for the aforementioned scenario would look more or less like this (the regular expression
for time and UUID are simplified and most likely invalid but we want to keep things very simple in this example):
[source,groovy,indent=0]
----
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/someUrl'
body([
time : value(consumer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value(consumer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "foo"
])
}
response {
status 200
body([
time : value(producer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value([producer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "bar"
])
}
}
----
IMPORTANT: Please read the http://groovy-lang.org/json.html[Groovy docs related to JSON] to understand how to
properly structure the request / response bodies.
=== How to do Stubs versioning?
==== API Versioning
Let's try to answer a question what versioning really means. If you're referring to the API version then there are
different approaches.
- use Hypermedia, links and do not version your API by any means
- pass versions through headers / urls
I will not try to answer a question which approach is better. Whatever suit your needs and allows you to generate
business value should be picked.
Let's assume that you do version your API. In that case you should provide as many contracts as many versions you support.
You can create a subfolder for every version or append it to th contract name - whatever suits you more.
==== JAR versioning
If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.
Let's assume that you're doing Continuous Delivery / Deployment which means that you're generating a new version of
the jar each time you go through the pipeline and that jar can go to production at any time. For example your jar version
looks like this (it got built on the 20.10.2016 at 20:15:21) :
[source,groovy,indent=0]
----
1.0.0.20161020-201521-RELEASE
----
In that case your generated stub jar will look like this.
[source,groovy,indent=0]
----
1.0.0.20161020-201521-RELEASE-stubs.jar
----
In this case you should inside your `application.yml` or `@AutoConfigureStubRunner` when referencing stubs provide the
latest version of the stubs. You can do that by passing the `+` sign. Example
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
----
If the versioning however is fixed (e.g. `1.0.4.RELEASE` or `2.1.1`) then you have to set the concrete value of the jar
version. Example for 2.1.1.
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:2.1.1:stubs:8080"})
----
==== Dev or prod stubs
You can manipulate the classifier to run the tests against current development version of the stubs of other services
or the ones that were deployed to production. If you alter your build to deploy the stubs with the `prod-stubs` classifier
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.
Example of tests using development version of stubs
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
----
Example of tests using production version of stubs
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:prod-stubs:8080"})
----
You can pass those values also via properties from your deployment pipeline.
=== Common repo with contracts
Another way of storing contracts other than having them with the producer is keeping them in a common place.
It can be related to security issues where the consumers can't clone the producer's code. Also if you keep
contracts in a single place then you, as a producer, will know how many consumers you have and which
consumer will you break with your local changes.
==== Repo structure
Let's assume that we have a producer with coordinates `com.example:server` and 3 consumers: `client1`,
`client2`, `client3`. Then in the repository with common contracts you would have the following setup
(which you can checkout https://github.com/spring-cloud/spring-cloud-contract/tree/1.0.x/samples/standalone/contracts[here]:
[source,bash,indent=0]
----
├── com
│   └── example
│   └── server
│   ├── client1
│   │   └── expectation.groovy
│   ├── client2
│   │   └── expectation.groovy
│   ├── client3
│   │   └── expectation.groovy
│   └── pom.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
└── assembly
└── contracts.xml
----
As you can see the under the slash-delimited groupid `/` artifact id folder (`com/example/server`) you have
expectations of the 3 consumers (`client1`, `client2` and `client3`). Expectations are the standard Groovy DSL
contract files as described throughout this documentation. This repository has to produce a JAR file that maps
one to one to the contents of the repo.
Example of a `pom.xml` inside the `server` folder.
[source,xml,indent=0]
----
include::{introduction_url}/samples/standalone/contracts/com/example/server/pom.xml[indent=0]
----
As you can see there are no dependencies other than the Spring Cloud Contract Maven Plugin.
Those poms are necessary for the consumer side to run `mvn clean install -DskipTests` to locally install
stubs of the producer project.
The `pom.xml` in the root folder can look like this:
[source,xml,indent=0]
----
include::{introduction_url}/samples/standalone/contracts/pom.xml[indent=0]
----
It's using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:
[source,xml,indent=0]
----
include::{introduction_url}/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]
----
include::{introduction_url}/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml[tags=remote_config,indent=0]
----
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.
=== How can I debug the request/response being sent by the generated tests client?
The generated tests all boil down to RestAssured in some form or fashion which relies on https://hc.apache.org/httpcomponents-client-ga/[Apache HttpClient]. HttpClient has a facility called https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging[wire logging] which logs the entire request and response to HttpClient. Spring Boot has a logging https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html[common application property] for doing this sort of thing, just add this to your application properties
[source,properties,indent=0]
----
logging.level.org.apache.http.wire=DEBUG
----
==== How can I debug the mapping/request/response being sent by WireMock?
Starting from version `1.2.0` we turn on WireMock logging to
info and the WireMock notifier to being verbose. Now you will
exactly know what request was received by WireMock server and which
matching response definition was picked.
To turn off this feature just bump WireMock logging to `ERROR`
[source,properties,indent=0]
----
logging.level.com.github.tomakehurst.wiremock=ERROR
----
==== How can I see what got registered in the HTTP server stub?
You can use the `mappingsOutputFolder` property on `@AutoConfigureStubRunner` or `StubRunnerRule`
to dump all mappings per artifact id. Also the port at which the given stub server was
started will be attached.
==== Can I reference the request from the response?
Yes! With version 1.1.0 we've added such a possibility. On the HTTP stub server side we're providing support
for this for WireMock. In case of other HTTP server stubs you'll have to implement the approach yourself.
==== Can I reference text from file?
Yes! With version 1.2.0 we've added such a possibility. It's enough to call `file(...)` method in the
DSL and provide a path relative to where the contract lays.

View File

@@ -1,4 +1,4 @@
=== Introduction
== Spring Cloud Contract Verifier Introduction
TIP: The Accurest project was initially started by Marcin Grzejszczak and Jakub Kubrynski (http://codearte.io[codearte.io])
@@ -13,13 +13,13 @@ Full test is generated by Spring Cloud Contract Verifier.
Spring Cloud Contract Verifier moves TDD to the level of software architecture.
==== Why?
=== Why?
Let us assume that we have a system comprising of multiple microservices:
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Deps.png[Microservices Architecture]
===== Testing issues
==== Testing issues
If we wanted to test the application in top left corner if it can communicate with other services then we could do one of two things:
@@ -63,7 +63,7 @@ image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{bra
Spring Cloud Contract Verifier gives you the certainty that the stubs that you're using were created by the service that you're calling. Also if you can use them it means that they were
tested against the producer's side. In other words - you can trust those stubs.
==== Purposes
=== Purposes
The main purposes of Spring Cloud Contract Verifier with Stub Runner are:
@@ -77,9 +77,9 @@ Let's assume that we have a business use case of fraud check. If a user can be a
we would assume that you would create 2 contracts. One for the positive and one for the negative fraud case.
Contract tests are used to test contracts between applications and not to simulate full behaviour.
==== How
=== How
===== Define the contract
==== Define the contract
As consumers we need to define what exactly we want to achieve. We need to formulate our expectations. That's why we write the following contract.
@@ -90,7 +90,7 @@ Lets assume that wed like to send the request containing the id of the cli
include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[]
----
===== Client Side
==== Client Side
Spring Cloud Contract will generate stubs, which you can use during client side testing.
You will have a WireMock instance / Messaging route up and running that simulates the service Y.
@@ -112,7 +112,7 @@ include::{introduction_url}/samples/standalone/dsl/http-client/src/test/java/com
After that, during the tests Spring Cloud Contract will automatically find the stubs (simulating the real service) in Maven repository and expose them on configured (or random) port.
===== Server Side
==== Server Side
Being a service Y since you are developing your stub, you need to be sure that it's actually resembling your
concrete implementation. You can't have a situation where your stub acts in one way and your application on
@@ -146,7 +146,7 @@ public void validate_shouldMarkClientAsFraud() throws Exception {
}
----
==== Step by step guide to CDC
=== Step by step guide to CDC
Let's take an example of Fraud Detection and Loan Issuance process. The business scenario is such that we want to issue loans to people but don't want them to steal the money from us. The current implementation of our system grants loans to everybody.
@@ -163,7 +163,7 @@ The https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples/
TIP: In this case the ownership of the contracts lays on the producer side. It means that physically
all the contract are present in the producer's repository
===== Technical note
==== Technical note
If using the *SNAPSHOT* / *Milestone* / *Release Candidate* versions please add the following section to your
@@ -179,7 +179,7 @@ include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=repo
include::{introduction_url}/samples/standalone/dsl/http-server/build.gradle[tags=deps_repos,indent=0]
----
===== Consumer side (Loan Issuance)
==== Consumer side (Loan Issuance)
As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):
@@ -353,7 +353,7 @@ What we did until now is an iterative process. We can play around with the contr
Once we're satisfied with the results and the test passes publish a PR to the server side. Currently the consumer side work is done.
===== Producer side (Fraud Detection server)
==== Producer side (Fraud Detection server)
As a developer of the Fraud Detection server (a server to the Loan Issuance service):
@@ -470,7 +470,7 @@ git push origin master
Then we assume that your CI would run sth like `./mvnw clean deploy` which would publish both the application and the stub artifcats.
===== Consumer side (Loan Issuance) final step
==== Consumer side (Loan Issuance) final step
As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):
@@ -495,403 +495,31 @@ include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{b
And that's it!
==== Dependencies
=== Dependencies
The best way to add the dependencies is to just use the proper `starter` dependency.
For `stub-runner` use `spring-cloud-starter-stub-runner` and when you're using a plugin just add
`spring-cloud-starter-contract-verifier`.
==== Additional links
=== Additional links
Below you can find some resources related to Spring Cloud Contract Verifier and Stub Runner. Note that some can be outdated since the Spring Cloud Contract Verifier project
is under constant development.
===== Spring Cloud Contract video
==== Spring Cloud Contract video
You can check out the video from the Warsaw JUG about Spring Cloud Contract:
video::sAAklvxmPmk[youtube,start=538,width=640,height=480]
===== Readings
==== Readings
- http://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura[Slides from Marcin Grzejszczak's talk about Accurest]
- http://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog]
- http://toomuchcoding.com/blog/categories/spring-cloud-contract/[Spring Cloud Contract related articles from Marcin Grzejszczak's blog]
- http://groovy-lang.org/json.html[Groovy docs regarding JSON]
==== Samples
=== Samples
Here you can find some https://github.com/spring-cloud-samples/spring-cloud-contract-samples[samples].
=== FAQ
==== Why use Spring Cloud Contract Verifier and not X ?
For the time being Spring Cloud Contract Verifier is a JVM based tool. So it could be your first pick when you're already creating
software for the JVM. This project has a lot of really interesting features but especially quite a few of them definitely make
Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Contract (CDC) tooling. Out of many the most interesting are:
- Possibility to do CDC with messaging
- Clear and easy to use, statically typed DSL
- Possibility to copy paste your current JSON file to the contract and only edit its elements
- Automatic generation of tests from the defined Contract
- Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory
- Spring Cloud integration - no discovery service is needed for integration tests
==== What is this value(consumer(), producer()) ?
One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
What typically makes that difficult are the hard-coded values of request / response elements. For example dates or ids.
Imagine the following JSON request
[source,json,indent=0]
----
{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}
----
and JSON response
[source,json,indent=0]
----
{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}
----
Imagine the pain required to set proper value of the `time` field (let's assume that this content is generated by the
database) by changing the clock in the system or providing stub implementations of data providers. The same is related
to the field called `id`. Will you create a stubbed implementation of UUID generator? Makes little sense...
So as a consumer you would like to send a request that matches any form of a time or any UUID. That way your system
will work as usual - will generate data and you won't have to stub anything out. Let's assume that in case of the aforementioned
JSON the most important part is the `body` field. You can focus on that and provide matching for other fields. In other words
you would like the stub to work like this:
[source,json,indent=0]
----
{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "foo"
}
----
As far as the response goes as a consumer you need a concrete value that you can operate on. So such a JSON is valid
[source,json,indent=0]
----
{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}
----
As you could see in the previous sections we generate tests from contracts. So from the producer's side the situation looks
much different. We're parsing the provided contract and in the test we want to send a real request to your endpoints.
So for the case of a producer for the request we can't have any sort of matching. We need concrete values that the
producer's backend can work on. Such a JSON would be a valid one:
[source,json,indent=0]
----
{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}
----
On the other hand from the point of view of the validity of the contract the response doesn't necessarily have to
contain concrete values of `time` or `id`. Let's say that you generate those on the producer side - again, you'd
have to do a lot of stubbing to ensure that you always return the same values. That's why from the producer's side
what you might want is the following response:
[source,json,indent=0]
----
{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "bar"
}
----
How can you then provide one time a matcher for the consumer and a concrete value for the producer and vice versa?
In Spring Cloud Contract we're allowing you to provide a *dynamic value*. That means that it can differ for both
sides of the communication. You can pass the values:
Either via the `value` method
[source,groovy,indent=0]
----
value(consumer(...), producer(...))
value(stub(...), test(...))
value(client(...), server(...))
----
or using the `$()` method
[source,groovy,indent=0]
----
$(consumer(...), producer(...))
$(stub(...), test(...))
$(client(...), server(...))
----
You can read more about this in the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl[Contract DSL section].
Calling `value()` or `$()` tells Spring Cloud Contract that you will be passing a dynamic value.
Inside the `consumer()` method you pass the value that should be used on the consumer side (in the generated stub).
Inside the `producer()` method you pass the value that should be used on the producer side (in the generated test).
TIP: If on one side you have passed the regular expression and you haven't passed the other, then the
other side will get auto-generated.
Most often you will use that method together with the `regex` helper method. E.g. `consumer(regex('[0-9]{10}'))`.
To sum it up the contract for the aforementioned scenario would look more or less like this (the regular expression
for time and UUID are simplified and most likely invalid but we want to keep things very simple in this example):
[source,groovy,indent=0]
----
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/someUrl'
body([
time : value(consumer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value(consumer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "foo"
])
}
response {
status 200
body([
time : value(producer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value([producer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "bar"
])
}
}
----
IMPORTANT: Please read the http://groovy-lang.org/json.html[Groovy docs related to JSON] to understand how to
properly structure the request / response bodies.
==== How to do Stubs versioning?
===== API Versioning
Let's try to answer a question what versioning really means. If you're referring to the API version then there are
different approaches.
- use Hypermedia, links and do not version your API by any means
- pass versions through headers / urls
I will not try to answer a question which approach is better. Whatever suit your needs and allows you to generate
business value should be picked.
Let's assume that you do version your API. In that case you should provide as many contracts as many versions you support.
You can create a subfolder for every version or append it to th contract name - whatever suits you more.
===== JAR versioning
If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.
Let's assume that you're doing Continuous Delivery / Deployment which means that you're generating a new version of
the jar each time you go through the pipeline and that jar can go to production at any time. For example your jar version
looks like this (it got built on the 20.10.2016 at 20:15:21) :
[source,groovy,indent=0]
----
1.0.0.20161020-201521-RELEASE
----
In that case your generated stub jar will look like this.
[source,groovy,indent=0]
----
1.0.0.20161020-201521-RELEASE-stubs.jar
----
In this case you should inside your `application.yml` or `@AutoConfigureStubRunner` when referencing stubs provide the
latest version of the stubs. You can do that by passing the `+` sign. Example
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
----
If the versioning however is fixed (e.g. `1.0.4.RELEASE` or `2.1.1`) then you have to set the concrete value of the jar
version. Example for 2.1.1.
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:2.1.1:stubs:8080"})
----
===== Dev or prod stubs
You can manipulate the classifier to run the tests against current development version of the stubs of other services
or the ones that were deployed to production. If you alter your build to deploy the stubs with the `prod-stubs` classifier
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.
Example of tests using development version of stubs
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
----
Example of tests using production version of stubs
[source,java,indent=0]
----
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:prod-stubs:8080"})
----
You can pass those values also via properties from your deployment pipeline.
==== Common repo with contracts
Another way of storing contracts other than having them with the producer is keeping them in a common place.
It can be related to security issues where the consumers can't clone the producer's code. Also if you keep
contracts in a single place then you, as a producer, will know how many consumers you have and which
consumer will you break with your local changes.
===== Repo structure
Let's assume that we have a producer with coordinates `com.example:server` and 3 consumers: `client1`,
`client2`, `client3`. Then in the repository with common contracts you would have the following setup
(which you can checkout https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples/standalone/contracts[here]:
[source,bash,indent=0]
----
├── com
│   └── example
│   └── server
│   ├── client1
│   │   └── expectation.groovy
│   ├── client2
│   │   └── expectation.groovy
│   ├── client3
│   │   └── expectation.groovy
│   └── pom.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
└── assembly
└── contracts.xml
----
As you can see the under the slash-delimited groupid `/` artifact id folder (`com/example/server`) you have
expectations of the 3 consumers (`client1`, `client2` and `client3`). Expectations are the standard Groovy DSL
contract files as described throughout this documentation. This repository has to produce a JAR file that maps
one to one to the contents of the repo.
Example of a `pom.xml` inside the `server` folder.
[source,xml,indent=0]
----
include::{introduction_url}/samples/standalone/contracts/com/example/server/pom.xml[indent=0]
----
As you can see there are no dependencies other than the Spring Cloud Contract Maven Plugin.
Those poms are necessary for the consumer side to run `mvn clean install -DskipTests` to locally install
stubs of the producer project.
The `pom.xml` in the root folder can look like this:
[source,xml,indent=0]
----
include::{introduction_url}/samples/standalone/contracts/pom.xml[indent=0]
----
It's using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:
[source,xml,indent=0]
----
include::{introduction_url}/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]
----
include::{introduction_url}/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml[tags=remote_config,indent=0]
----
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.
==== How can I debug the request/response being sent by the generated tests client?
The generated tests all boil down to RestAssured in some form or fashion which relies on https://hc.apache.org/httpcomponents-client-ga/[Apache HttpClient]. HttpClient has a facility called https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging[wire logging] which logs the entire request and response to HttpClient. Spring Boot has a logging https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html[common application property] for doing this sort of thing, just add this to your application properties
[source,properties,indent=0]
----
logging.level.org.apache.http.wire=DEBUG
----
==== How can I debug the mapping/request/response being sent by WireMock?
Starting from version `1.2.0` we turn on WireMock logging to
info and the WireMock notifier to being verbose. Now you will
exactly know what request was received by WireMock server and which
matching response definition was picked.
To turn off this feature just bump WireMock logging to `ERROR`
[source,properties,indent=0]
----
logging.level.com.github.tomakehurst.wiremock=ERROR
----
==== How can I see what got registered in the HTTP server stub?
You can use the `mappingsOutputFolder` property on `@AutoConfigureStubRunner` or `StubRunnerRule`
to dump all mappings per artifact id. Also the port at which the given stub server was
started will be attached.
==== Can I reference the request from the response?
Yes! With version 1.1.0 we've added such a possibility. On the HTTP stub server side we're providing support
for this for WireMock. In case of other HTTP server stubs you'll have to implement the approach yourself.
==== Can I reference text from file?
Yes! With version 1.2.0 we've added such a possibility. It's enough to call `file(...)` method in the
DSL and provide a path relative to where the contract lays.
Here you can find some https://github.com/spring-cloud-samples/spring-cloud-contract-samples[samples].

View File

@@ -1,9 +1,9 @@
=== Spring Cloud Contract Verifier Messaging
== 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
=== Integrations
You can use one of the four integration configurations:
@@ -38,7 +38,7 @@ testCompile "org.springframework.cloud:spring-cloud-stream-test-support"
----
==== Manual Integration Testing
=== 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
@@ -64,7 +64,7 @@ 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
=== 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.
@@ -82,7 +82,7 @@ IMPORTANT: The destination passed to `messageFrom` or `sentTo` can have differen
Example for Camel:
===== Scenario 1 (no input message)
==== Scenario 1 (no input message)
For the given contract:
@@ -105,7 +105,7 @@ And the following Spock test would be created:
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_method_test]
----
===== Scenario 2 (output triggered by input)
==== Scenario 2 (output triggered by input)
For the given contract:
@@ -128,7 +128,7 @@ And the following Spock test would be created:
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_message_spock]
----
===== Scenario 3 (no output message)
==== Scenario 3 (no output message)
For the given contract:
@@ -151,7 +151,7 @@ And the following Spock test would be created:
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_no_output_spock]
----
==== Consumer Stub Side generation
=== 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.

View File

@@ -1,15 +1,15 @@
=== Spring Cloud Contract Verifier HTTP
== Spring Cloud Contract Verifier Setup
==== Gradle Project
=== Gradle Project
===== Prerequisites
==== 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
==== Add gradle plugin with dependencies
[source,groovy,indent=0]
----
@@ -41,7 +41,7 @@ dependencies {
}
----
====== Gradle and Rest Assured 2.0
==== Gradle and Rest Assured 2.0
By default Rest Assured 3.x is added to the classpath. However in order to give the users the
opportunity to use Rest Assured 2.x it's enough to add it to the plugins classpath.
@@ -71,7 +71,7 @@ depenendencies {
That way the plugin will automatically see that Rest Assured 2.x is present on the classpath
and will modify the imports accordingly.
====== Snapshot versions for Gradle
==== 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:
@@ -81,7 +81,7 @@ include::{standalone_samples_path}/http-server/build.gradle[tags=repos,indent=0]
}
----
====== Add stubs
==== Add stubs
By default Spring Cloud Contract Verifier is looking for stubs in `src/test/resources/contracts` directory.
@@ -100,11 +100,11 @@ Spring Cloud Contract Verifier will create test class `defaultBasePackage.MyServ
- `shouldCreateUser()`
- `shouldReturnUser()`
===== Run plugin
==== 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 setup
Default Gradle Plugin setup creates the following Gradle part of the build (it's a pseudocode)
@@ -156,7 +156,7 @@ publishing {
}
----
===== Configure plugin
==== Configure plugin
To change default configuration just add `contracts` snippet to your Gradle config
@@ -169,7 +169,7 @@ contracts {
}
----
====== Configuration options
==== 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 []
@@ -192,7 +192,7 @@ The following properties are used when you want to provide where the JAR with co
- **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
==== 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.
@@ -204,7 +204,7 @@ include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/f
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
==== 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:
@@ -241,7 +241,7 @@ By providing the `baseClassForTests` we have a fallback in case mapping didn't s
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
==== Invoking generated tests
To ensure that provider side is complaint with defined contracts, you need to invoke:
@@ -250,7 +250,7 @@ To ensure that provider side is complaint with defined contracts, you need to in
./gradlew generateContractTests test
----
===== Spring Cloud Contract Verifier on consumer side
==== 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:
@@ -291,9 +291,9 @@ class LoanApplicationServiceSpec extends Specification {
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
=== Using in your Maven project
===== Add maven plugin
==== Add maven plugin
Add the Spring Cloud Contract BOM
@@ -311,7 +311,7 @@ include::{standalone_samples_path}/http-server/pom.xml[tags=contract_maven_plugi
You can read more in the https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/[Spring Cloud Contract Maven Plugin Docs]
====== Maven and Rest Assured 2.0
==== Maven and Rest Assured 2.0
By default Rest Assured 3.x is added to the classpath. However in order to give the users the
opportunity to use Rest Assured 2.x it's enough to add it to the plugins classpath.
@@ -368,7 +368,7 @@ opportunity to use Rest Assured 2.x it's enough to add it to the plugins classpa
That way the plugin will automatically see that Rest Assured 3.x is present on the classpath
and will modify the imports accordingly.
====== Snapshot versions for Maven
==== Snapshot versions for Maven
For Snapshot / Milestone versions you have to add the following section to your `pom.xml`
@@ -377,7 +377,7 @@ For Snapshot / Milestone versions you have to add the following section to your
include::{standalone_samples_path}/http-server/pom.xml[tags=repos,indent=0]
----
===== Add stubs
==== 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.
@@ -394,11 +394,11 @@ Spring Cloud Contract Verifier will create test class `defaultBasePackage.MyServ
- `shouldCreateUser()`
- `shouldReturnUser()`
===== Run plugin
==== 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
==== Configure plugin
To change default configuration just add `configuration` section to plugin definition or `execution` definition.
@@ -423,7 +423,7 @@ To change default configuration just add `configuration` section to plugin defin
</plugin>
----
====== Important configuration options
==== 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. If not set the value will be picked from `baseClassForTests`'s package and from
@@ -457,7 +457,7 @@ If you want to download your contract definitions from a Maven repository you ca
We cache only non-snapshot, explicitly provided versions (e.g. `+` or `1.0.0.BUILD-SNAPSHOT` won't get cached).
By default this feature is turned on.
====== Single base class for all tests
==== 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.
@@ -479,7 +479,7 @@ class MvcSpec extends Specification {
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
==== 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:
@@ -517,7 +517,7 @@ By providing the `baseClassForTests` we have a fallback in case mapping didn't s
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
==== Invoking generated tests
Spring Cloud Contract Maven Plugin generates verification code into directory `/generated-test-sources/contractVerifier` and attach this directory to `testCompile` goal.
@@ -557,9 +557,9 @@ For Groovy Spock code use:
To ensure that provider side is complaint with defined contracts, you need to invoke `mvn generateTest test`
===== FAQ with Maven Plugin
==== FAQ with Maven Plugin
====== Maven Plugin and STS
==== Maven Plugin and STS
In case you see the following exception while using STS
@@ -616,7 +616,7 @@ In order to fix this issue just provide the following section in your `pom.xml`
</build>
----
===== Spring Cloud Contract Verifier on consumer side
==== 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.
@@ -676,7 +676,7 @@ public class LoanApplicationServiceTests {
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
=== 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.
@@ -699,7 +699,7 @@ More details about WireMock scenarios can be found under http://wiremock.org/sta
Spring Cloud Contract Verifier will also generate tests with guaranteed order of execution.
==== Stubs and transitive dependencies
=== 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

View File

@@ -1,4 +1,4 @@
=== Spring Cloud Contract Stub Runner
== 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.
@@ -8,7 +8,7 @@ Copying the JSON files / setting the client side for messaging manually is out o
That's why we'll introduce Spring Cloud Contract Stub Runner that can download and run the stubs
automatically for you.
==== Snapshot versions
=== Snapshot versions
Add the additional snapshot repository to your build.gradle to use snapshot versions which are automatically uploaded after every successful build:
@@ -24,7 +24,7 @@ include::{standalone_samples_path}/http-server/pom.xml[tags=repos,indent=0]
include::{standalone_samples_path}/http-server/build.gradle[tags=repos,indent=0]
----
==== Publishing stubs as JARs
=== 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.
@@ -58,7 +58,7 @@ include::{stubrunner_core_path}/README.adoc[]
Some of the properties that are repetitive can be set using system properties or configuration properties (for Spring). Here are their names with their default values:
[frame="topbot",options="header"]
|======================
|===============
| Property name | Default value | Description
|stubrunner.minPort|10000| Minimal value of a port for a started WireMock with stubs
|stubrunner.maxPort|15000| Minimal value of a port for a started WireMock with stubs
@@ -70,9 +70,9 @@ Some of the properties that are repetitive can be set using system properties or
|stubrunner.password|| Optional password to access the tool that stores the JARs with stubs
|stubrunner.stubsPerConsumer|false| Set to `true` if you want to use different stubs per each consumer instead of registering all stubs for every consumer
|stubrunner.consumerName|| If you want to use stubs per consumer and want to override the consumer name just change this value
|======================
|===============
===== Stub runner stubs ids
==== Stub runner stubs ids
You can provide the stubs to download via the `stubrunner.ids` system property. They follow the following pattern:

View File

@@ -1,4 +1,4 @@
=== Stub Runner for Messaging
== Stub Runner for Messaging
Stub Runner has the functionality to run the published stubs in memory. It can integrate with the following frameworks out of the box
@@ -9,7 +9,7 @@ Stub Runner has the functionality to run the published stubs in memory. It can i
It also provides points of entry to integrate with any other solution on the market.
==== Stub triggering
=== Stub triggering
To trigger a message it's enough to use the `StubTrigger` interface:
@@ -22,28 +22,28 @@ For convenience the `StubFinder` interface extends `StubTrigger` so it's enough
`StubTrigger` gives you the following options to trigger a message:
===== Trigger by label
==== Trigger by label
[source,groovy]
----
include::{tests_path}/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger,indent=0]
----
====== Trigger by group and artifact ids
==== Trigger by group and artifact ids
[source,groovy]
----
include::{tests_path}/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=trigger_group_artifact,indent=0]
----
====== Trigger by artifact ids
==== Trigger by artifact ids
[source,groovy]
----
include::{tests_path}/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=trigger_artifact,indent=0]
----
===== Trigger all messages
==== Trigger all messages
[source,groovy]
----