Sync docs from master to gh-pages
This commit is contained in:
@@ -844,463 +844,6 @@ constant development.</simpara>
|
||||
<link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples">samples</link>.</simpara>
|
||||
</section>
|
||||
</chapter>
|
||||
<chapter xml:id="_spring_cloud_contract_faq">
|
||||
<title>Spring Cloud Contract FAQ</title>
|
||||
<section xml:id="_why_use_spring_cloud_contract_verifier_and_not_x">
|
||||
<title>Why use Spring Cloud Contract Verifier and not X ?</title>
|
||||
<simpara>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:</simpara>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>Possibility to do CDC with messaging</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Clear and easy to use, statically typed DSL</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Possibility to copy paste your current JSON file to the contract and only edit its elements</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Automatic generation of tests from the defined Contract</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Spring Cloud integration - no discovery service is needed for integration tests</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="_what_is_this_value_consumer_producer">
|
||||
<title>What is this value(consumer(), producer()) ?</title>
|
||||
<simpara>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</simpara>
|
||||
<programlisting language="json" linenumbering="unnumbered">{
|
||||
"time" : "2016-10-10 20:10:15",
|
||||
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
|
||||
"body" : "foo"
|
||||
}</programlisting>
|
||||
<simpara>and JSON response</simpara>
|
||||
<programlisting language="json" linenumbering="unnumbered">{
|
||||
"time" : "2016-10-10 21:10:15",
|
||||
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
|
||||
"body" : "bar"
|
||||
}</programlisting>
|
||||
<simpara>Imagine the pain required to set proper value of the <literal>time</literal> 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 <literal>id</literal>. Will you create a stubbed implementation of UUID generator? Makes little sense…​</simpara>
|
||||
<simpara>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 <literal>body</literal> field. You can focus on that and provide matching for other fields. In other words
|
||||
you would like the stub to work like this:</simpara>
|
||||
<programlisting language="json" linenumbering="unnumbered">{
|
||||
"time" : "SOMETHING THAT MATCHES TIME",
|
||||
"id" : "SOMETHING THAT MATCHES UUID",
|
||||
"body" : "foo"
|
||||
}</programlisting>
|
||||
<simpara>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</simpara>
|
||||
<programlisting language="json" linenumbering="unnumbered">{
|
||||
"time" : "2016-10-10 21:10:15",
|
||||
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
|
||||
"body" : "bar"
|
||||
}</programlisting>
|
||||
<simpara>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:</simpara>
|
||||
<programlisting language="json" linenumbering="unnumbered">{
|
||||
"time" : "2016-10-10 20:10:15",
|
||||
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
|
||||
"body" : "foo"
|
||||
}</programlisting>
|
||||
<simpara>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 <literal>time</literal> or <literal>id</literal>. 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:</simpara>
|
||||
<programlisting language="json" linenumbering="unnumbered">{
|
||||
"time" : "SOMETHING THAT MATCHES TIME",
|
||||
"id" : "SOMETHING THAT MATCHES UUID",
|
||||
"body" : "bar"
|
||||
}</programlisting>
|
||||
<simpara>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 <emphasis role="strong">dynamic value</emphasis>. That means that it can differ for both
|
||||
sides of the communication. You can pass the values:</simpara>
|
||||
<simpara>Either via the <literal>value</literal> method</simpara>
|
||||
<programlisting language="groovy" linenumbering="unnumbered">value(consumer(...), producer(...))
|
||||
value(stub(...), test(...))
|
||||
value(client(...), server(...))</programlisting>
|
||||
<simpara>or using the <literal>$()</literal> method</simpara>
|
||||
<programlisting language="groovy" linenumbering="unnumbered">$(consumer(...), producer(...))
|
||||
$(stub(...), test(...))
|
||||
$(client(...), server(...))</programlisting>
|
||||
<simpara>You can read more about this in the <link xl:href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl">Contract DSL section</link>.</simpara>
|
||||
<simpara>Calling <literal>value()</literal> or <literal>$()</literal> tells Spring Cloud Contract that you will be passing a dynamic value.
|
||||
Inside the <literal>consumer()</literal> method you pass the value that should be used on the consumer side (in the generated stub).
|
||||
Inside the <literal>producer()</literal> method you pass the value that should be used on the producer side (in the generated test).</simpara>
|
||||
<tip>
|
||||
<simpara>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.</simpara>
|
||||
</tip>
|
||||
<simpara>Most often you will use that method together with the <literal>regex</literal> helper method. E.g. <literal>consumer(regex('[0-9]{10}'))</literal>.</simpara>
|
||||
<simpara>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):</simpara>
|
||||
<programlisting language="groovy" linenumbering="unnumbered">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"
|
||||
])
|
||||
}
|
||||
}</programlisting>
|
||||
<important>
|
||||
<simpara>Please read the <link xl:href="http://groovy-lang.org/json.html">Groovy docs related to JSON</link> to understand how to
|
||||
properly structure the request / response bodies.</simpara>
|
||||
</important>
|
||||
</section>
|
||||
<section xml:id="_how_to_do_stubs_versioning">
|
||||
<title>How to do Stubs versioning?</title>
|
||||
<section xml:id="_api_versioning">
|
||||
<title>API Versioning</title>
|
||||
<simpara>Let’s try to answer a question what versioning really means. If you’re referring to the API version then there are
|
||||
different approaches.</simpara>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>use Hypermedia, links and do not version your API by any means</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>pass versions through headers / urls</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<simpara>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.</simpara>
|
||||
<simpara>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.</simpara>
|
||||
</section>
|
||||
<section xml:id="_jar_versioning">
|
||||
<title>JAR versioning</title>
|
||||
<simpara>If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.</simpara>
|
||||
<simpara>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) :</simpara>
|
||||
<programlisting language="groovy" linenumbering="unnumbered">1.0.0.20161020-201521-RELEASE</programlisting>
|
||||
<simpara>In that case your generated stub jar will look like this.</simpara>
|
||||
<programlisting language="groovy" linenumbering="unnumbered">1.0.0.20161020-201521-RELEASE-stubs.jar</programlisting>
|
||||
<simpara>In this case you should inside your <literal>application.yml</literal> or <literal>@AutoConfigureStubRunner</literal> when referencing stubs provide the
|
||||
latest version of the stubs. You can do that by passing the <literal>+</literal> sign. Example</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})</programlisting>
|
||||
<simpara>If the versioning however is fixed (e.g. <literal>1.0.4.RELEASE</literal> or <literal>2.1.1</literal>) then you have to set the concrete value of the jar
|
||||
version. Example for 2.1.1.</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:2.1.1:stubs:8080"})</programlisting>
|
||||
</section>
|
||||
<section xml:id="_dev_or_prod_stubs">
|
||||
<title>Dev or prod stubs</title>
|
||||
<simpara>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 <literal>prod-stubs</literal> classifier
|
||||
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.</simpara>
|
||||
<simpara>Example of tests using development version of stubs</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})</programlisting>
|
||||
<simpara>Example of tests using production version of stubs</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:prod-stubs:8080"})</programlisting>
|
||||
<simpara>You can pass those values also via properties from your deployment pipeline.</simpara>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="_common_repo_with_contracts">
|
||||
<title>Common repo with contracts</title>
|
||||
<simpara>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.</simpara>
|
||||
<section xml:id="_repo_structure">
|
||||
<title>Repo structure</title>
|
||||
<simpara>Let’s assume that we have a producer with coordinates <literal>com.example:server</literal> and 3 consumers: <literal>client1</literal>,
|
||||
<literal>client2</literal>, <literal>client3</literal>. Then in the repository with common contracts you would have the following setup
|
||||
(which you can checkout <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.0.x/samples/standalone/contracts">here</link>:</simpara>
|
||||
<programlisting language="bash" linenumbering="unnumbered">├── com
|
||||
│ └── example
|
||||
│ └── server
|
||||
│ ├── client1
|
||||
│ │ └── expectation.groovy
|
||||
│ ├── client2
|
||||
│ │ └── expectation.groovy
|
||||
│ ├── client3
|
||||
│ │ └── expectation.groovy
|
||||
│ └── pom.xml
|
||||
├── mvnw
|
||||
├── mvnw.cmd
|
||||
├── pom.xml
|
||||
└── src
|
||||
└── assembly
|
||||
└── contracts.xml</programlisting>
|
||||
<simpara>As you can see the under the slash-delimited groupid <literal>/</literal> artifact id folder (<literal>com/example/server</literal>) you have
|
||||
expectations of the 3 consumers (<literal>client1</literal>, <literal>client2</literal> and <literal>client3</literal>). 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.</simpara>
|
||||
<simpara>Example of a <literal>pom.xml</literal> inside the <literal>server</literal> folder.</simpara>
|
||||
<programlisting language="xml" linenumbering="unnumbered"><?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></programlisting>
|
||||
<simpara>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 <literal>mvn clean install -DskipTests</literal> to locally install
|
||||
stubs of the producer project.</simpara>
|
||||
<simpara>The <literal>pom.xml</literal> in the root folder can look like this:</simpara>
|
||||
<programlisting language="xml" linenumbering="unnumbered"><?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></programlisting>
|
||||
<simpara>It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:</simpara>
|
||||
<programlisting language="xml" linenumbering="unnumbered"><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></programlisting>
|
||||
</section>
|
||||
<section xml:id="_workflow">
|
||||
<title>Workflow</title>
|
||||
<simpara>The workflow would look similar to the one presented in the <literal>Step by step guide to CDC</literal>. 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.</simpara>
|
||||
</section>
|
||||
<section xml:id="_consumer">
|
||||
<title>Consumer</title>
|
||||
<simpara>When the <emphasis role="strong">consumer</emphasis> 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. <literal>com/example/server</literal>)
|
||||
and runs <literal>mvn clean install -DskipTests</literal> to install locally the stubs converted from the contracts.</simpara>
|
||||
<tip>
|
||||
<simpara>You need to have <link xl:href="http://maven.apache.org/download.cgi">Maven installed locally</link></simpara>
|
||||
</tip>
|
||||
</section>
|
||||
<section xml:id="_producer">
|
||||
<title>Producer</title>
|
||||
<simpara>As a <emphasis role="strong">producer</emphasis> it’s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
|
||||
of the JAR containing the contracts:</simpara>
|
||||
<programlisting language="xml" linenumbering="unnumbered"><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></programlisting>
|
||||
<simpara>With this setup the JAR with groupid <literal>com.example.standalone</literal> and artifactid <literal>contracts</literal> will be downloaded
|
||||
from <literal><link xl:href="http://link/to/your/nexus/or/artifactory/or/sth">http://link/to/your/nexus/or/artifactory/or/sth</link></literal>. It will be then unpacked in a local temporary folder
|
||||
and contracts present under the <literal>com/example/server</literal> 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.</simpara>
|
||||
<simpara>The rest of the flow looks the same.</simpara>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="_can_i_have_multiple_base_classes_for_tests">
|
||||
<title>Can I have multiple base classes for tests?</title>
|
||||
<simpara>Yes! Check out the <link xl:href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_different_base_classes_for_contracts">Different base classes for contracts</link> sections
|
||||
of either Gradle or Maven plugins.</simpara>
|
||||
</section>
|
||||
<section xml:id="_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client">
|
||||
<title>How can I debug the request/response being sent by the generated tests client?</title>
|
||||
<simpara>The generated tests all boil down to RestAssured in some form or fashion which relies on <link xl:href="https://hc.apache.org/httpcomponents-client-ga/">Apache HttpClient</link>. HttpClient has a facility called <link xl:href="https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging">wire logging</link> which logs the entire request and response to HttpClient. Spring Boot has a logging <link xl:href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html">common application property</link> for doing this sort of thing, just add this to your application properties</simpara>
|
||||
<programlisting language="properties" linenumbering="unnumbered">logging.level.org.apache.http.wire=DEBUG</programlisting>
|
||||
<section xml:id="_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock">
|
||||
<title>How can I debug the mapping/request/response being sent by WireMock?</title>
|
||||
<simpara>Starting from version <literal>1.2.0</literal> 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.</simpara>
|
||||
<simpara>To turn off this feature just bump WireMock logging to <literal>ERROR</literal></simpara>
|
||||
<programlisting language="properties" linenumbering="unnumbered">logging.level.com.github.tomakehurst.wiremock=ERROR</programlisting>
|
||||
</section>
|
||||
<section xml:id="_how_can_i_see_what_got_registered_in_the_http_server_stub">
|
||||
<title>How can I see what got registered in the HTTP server stub?</title>
|
||||
<simpara>You can use the <literal>mappingsOutputFolder</literal> property on <literal>@AutoConfigureStubRunner</literal> or <literal>StubRunnerRule</literal>
|
||||
to dump all mappings per artifact id. Also the port at which the given stub server was
|
||||
started will be attached.</simpara>
|
||||
</section>
|
||||
<section xml:id="_can_i_reference_the_request_from_the_response">
|
||||
<title>Can I reference the request from the response?</title>
|
||||
<simpara>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.</simpara>
|
||||
</section>
|
||||
<section xml:id="_can_i_reference_text_from_file">
|
||||
<title>Can I reference text from file?</title>
|
||||
<simpara>Yes! With version 1.2.0 we’ve added such a possibility. It’s enough to call <literal>file(…​)</literal> method in the
|
||||
DSL and provide a path relative to where the contract lays.</simpara>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
<chapter xml:id="_spring_cloud_contract_verifier_setup">
|
||||
<title>Spring Cloud Contract Verifier Setup</title>
|
||||
<simpara>You can set up Spring Cloud Contract Verifier in either of two ways</simpara>
|
||||
|
||||
Reference in New Issue
Block a user