Sync docs from 2.1.x to gh-pages
This commit is contained in:
@@ -7,7 +7,7 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.regex.Pattern;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* If you want to use {@link Pattern} directly in your tests
|
||||
* then you can create a class resembling this one. It can
|
||||
* contain all the {@link Pattern} you want to use in the DSL.
|
||||
@@ -25,7 +25,7 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
* and {@code c()} for the consumer side.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> PatternUtils {
|
||||
|
||||
@@ -41,9 +41,9 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
|
||||
}
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Makes little sense but it's just an example ;)
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> Pattern ok() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"OK"</span>);
|
||||
@@ -54,7 +54,7 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.ClientDslProperty;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* DSL Properties passed to the DSL from the consumer's perspective.
|
||||
* That means that on the input side {@code Request} for HTTP
|
||||
* or {@code Input} for messaging you can have a regular expression.
|
||||
@@ -62,10 +62,10 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
* you have to have a concrete value.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ConsumerUtils {
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Consumer side property. By using the {@link ClientDslProperty}
|
||||
* you can omit most of boilerplate code from the perspective
|
||||
* of dynamic values. Example
|
||||
@@ -83,13 +83,13 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
* and which one to the producer.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> ClientDslProperty oldEnough() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// this example is not the best one and</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// theoretically you could just pass the regex instead of `ServerDslProperty` but</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// it's just to show some new tricks :)</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ClientDslProperty(PatternUtils.oldEnough(), <span class="hl-number">40</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ClientDslProperty(PatternUtils.oldEnough(), <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">40</xslthl:number>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.ServerDslProperty;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* DSL Properties passed to the DSL from the producer's perspective.
|
||||
* That means that on the input side {@code Request} for HTTP
|
||||
* or {@code Input} for messaging you have to have a concrete value.
|
||||
@@ -106,11 +106,11 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
* you can have a regular expression.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ProducerUtils {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Producer side property. By using the {@link ProducerUtils}
|
||||
* you can omit most of boilerplate code from the perspective
|
||||
* of dynamic values. Example
|
||||
@@ -126,7 +126,7 @@ maintain the static compatibility. Later in this document, you can see examples
|
||||
*
|
||||
* That way it's in the implementation that we decide what value we will pass to the consumer
|
||||
* and which one to the producer.
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> ServerDslProperty ok() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// this example is not the best one and</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// theoretically you could just pass the regex instead of `ServerDslProperty` but</span>
|
||||
@@ -204,7 +204,7 @@ then:
|
||||
}
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
|
||||
</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${value(ProducerUtils.ok())}"</span>
|
||||
|
||||
@@ -5,9 +5,9 @@ the project’s <a class="link" href="https://github.com/spring-cloud/spring
|
||||
next version. It covers the following versions upgrade paths:</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cloud-verifier-1.0-1.1" href="#cloud-verifier-1.0-1.1"></a>12.1 1.0.x → 1.1.x</h2></div></div></div><p>This section covers upgrading from version 1.0 to version 1.1.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_new_structure_of_generated_stubs" href="#_new_structure_of_generated_stubs"></a>12.1.1 New structure of generated stubs</h3></div></div></div><p>In <code class="literal">1.1.x</code> we have introduced a change to the structure of generated stubs. If you have
|
||||
been using the <code class="literal">@AutoConfigureWireMock</code> notation to use the stubs from the classpath,
|
||||
it no longer works. The following example shows how the <code class="literal">@AutoConfigureWireMock</code> notation
|
||||
used to work:</p><pre class="programlisting">@AutoConfigureWireMock(stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:/customer-stubs/mappings"</span>, port = <span class="hl-number">8084</span>)</pre><p>You must either change the location of the stubs to:
|
||||
used to work:</p><pre class="programlisting">@AutoConfigureWireMock(stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:/customer-stubs/mappings"</span>, port = <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8084</xslthl:number>)</pre><p>You must either change the location of the stubs to:
|
||||
<code class="literal">classpath:…​/META-INF/groupId/artifactId/version/mappings</code> or use the new
|
||||
classpath-based <code class="literal">@AutoConfigureStubRunner</code>, as shown in the following example:</p><pre class="programlisting">@AutoConfigureWireMock(stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:customer-stubs/META-INF/travel.components/customer-contract/1.0.2-SNAPSHOT/mappings/"</span>, port = <span class="hl-number">8084</span>)</pre><p>If you do not want to use <code class="literal">@AutoConfigureStubRunner</code> and you want to remain with the old
|
||||
classpath-based <code class="literal">@AutoConfigureStubRunner</code>, as shown in the following example:</p><pre class="programlisting">@AutoConfigureWireMock(stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:customer-stubs/META-INF/travel.components/customer-contract/1.0.2-SNAPSHOT/mappings/"</span>, port = <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8084</xslthl:number>)</pre><p>If you do not want to use <code class="literal">@AutoConfigureStubRunner</code> and you want to remain with the old
|
||||
structure, set your plugin tasks accordingly. The following example would work for the
|
||||
structure presented in the previous snippet.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- start of pom.xml --></span>
|
||||
@@ -90,7 +90,7 @@ detail.</p></div><div class="section"><div class="titlepage"><div><div><h3 class
|
||||
<code class="literal">TemplateProcessor</code> interface:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">path()</code></li><li class="listitem"><code class="literal">path(int index)</code></li></ul></div><p>See <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/388" target="_top">issue 388</a> for more
|
||||
detail.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_restassured_3_0" href="#_restassured_3_0"></a>12.2.4 RestAssured 3.0</h3></div></div></div><p>Rest Assured, used in the generated test classes, got bumped to <code class="literal">3.0</code>. If
|
||||
you manually set versions of Spring Cloud Contract and the release train
|
||||
you might see the following exception:</p><pre class="programlisting">Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:<span class="hl-number">3.1</span>:testCompile (default-testCompile) on project some-project: Compilation failure: Compilation failure:
|
||||
[ERROR] /some/path/SomeClass.java:[<span class="hl-number">4</span>,<span class="hl-number">39</span>] package com.jayway.restassured.response does not exist</pre><p>This exception will occur due to the fact that the tests got generated with
|
||||
you might see the following exception:</p><pre class="programlisting">Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3.1</xslthl:number>:testCompile (default-testCompile) on project some-project: Compilation failure: Compilation failure:
|
||||
[ERROR] /some/path/SomeClass.java:[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>,<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">39</xslthl:number>] package com.jayway.restassured.response does not exist</pre><p>This exception will occur due to the fact that the tests got generated with
|
||||
an old version of plugin and at test execution time you have an incompatible
|
||||
version of the release train (and vice versa).</p><p>Done via <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/267" target="_top">issue 267</a></p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cloud-verifier-1.2-2.0" href="#cloud-verifier-1.2-2.0"></a>12.3 1.2.x → 2.0.x</h2></div></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_wiremock.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__links.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11. Spring Cloud Contract WireMock </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top"> 13. Links</td></tr></table></div></body></html>
|
||||
@@ -73,7 +73,7 @@ different approaches.</p><div class="itemizedlist"><ul class="itemizedlist" styl
|
||||
business value should be picked.</p><p>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 the contract name - whatever suits you more.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_jar_versioning" href="#_jar_versioning"></a>3.4.2 JAR versioning</h3></div></div></div><p>If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.</p><p>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) :</p><pre class="programlisting"><span class="hl-number">1.0</span>.<span class="hl-number">0.20161020</span>-<span class="hl-number">201521</span>-RELEASE</pre><p>In that case your generated stub jar will look like this.</p><pre class="programlisting"><span class="hl-number">1.0</span>.<span class="hl-number">0.20161020</span>-<span class="hl-number">201521</span>-RELEASE-stubs.jar</pre><p>In this case you should inside your <code class="literal">application.yml</code> or <code class="literal">@AutoConfigureStubRunner</code> when referencing stubs provide the
|
||||
looks like this (it got built on the 20.10.2016 at 20:15:21) :</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.20161020</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">201521</xslthl:number>-RELEASE</pre><p>In that case your generated stub jar will look like this.</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.20161020</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">201521</xslthl:number>-RELEASE-stubs.jar</pre><p>In this case you should inside your <code class="literal">application.yml</code> or <code class="literal">@AutoConfigureStubRunner</code> when referencing stubs provide the
|
||||
latest version of the stubs. You can do that by passing the <code class="literal">+</code> sign. Example</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:stubs:8080"</span>})</pre><p>If the versioning however is fixed (e.g. <code class="literal">1.0.4.RELEASE</code> or <code class="literal">2.1.1</code>) then you have to set the concrete value of the jar
|
||||
version. Example for 2.1.1.</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:2.1.1:stubs:8080"</span>})</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dev_or_prod_stubs" href="#_dev_or_prod_stubs"></a>3.4.3 Dev or prod stubs</h3></div></div></div><p>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 <code class="literal">prod-stubs</code> classifier
|
||||
@@ -100,7 +100,7 @@ consumer you will break with your local changes.</p><div class="section"><div cl
|
||||
└── contracts.xml</pre><p>As you can see under the slash-delimited groupid <code class="literal">/</code> artifact id folder (<code class="literal">com/example/server</code>) you have
|
||||
expectations of the 3 consumers (<code class="literal">client1</code>, <code class="literal">client2</code> and <code class="literal">client3</code>). 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.</p><p>Example of a <code class="literal">pom.xml</code> inside the <code class="literal">server</code> folder.</p><pre class="programlisting"><span class="hl-directive" style="color: maroon"><?xml version="1.0" encoding="UTF-8"?></span>
|
||||
one to one to the contents of the repo.</p><p>Example of a <code class="literal">pom.xml</code> inside the <code class="literal">server</code> folder.</p><pre class="programlisting"><xslthl:directive xmlns:xslthl="http://xslthl.sourceforge.net/"><?xml version="1.0" encoding="UTF-8"?></xslthl:directive>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
@@ -211,7 +211,7 @@ one to one to the contents of the repo.</p><p>Example of a <code class="literal"
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></project></span></pre><p>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 <code class="literal">mvn clean install -DskipTests</code> to locally install
|
||||
stubs of the producer project.</p><p>The <code class="literal">pom.xml</code> in the root folder can look like this:</p><pre class="programlisting"><span class="hl-directive" style="color: maroon"><?xml version="1.0" encoding="UTF-8"?></span>
|
||||
stubs of the producer project.</p><p>The <code class="literal">pom.xml</code> in the root folder can look like this:</p><pre class="programlisting"><xslthl:directive xmlns:xslthl="http://xslthl.sourceforge.net/"><?xml version="1.0" encoding="UTF-8"?></xslthl:directive>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
@@ -682,14 +682,14 @@ dependencies {
|
||||
testCompile("org.springframework.cloud:spring-cloud-contract-pact")
|
||||
}</pre><p>
|
||||
</p><p>Next, just pass the URL of the Pact Broker to <code class="literal">repositoryRoot</code>, prefixed
|
||||
with <code class="literal">pact://</code> protocol. E.g. <code class="literal">pact://http://localhost:8085</code></p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
||||
with <code class="literal">pact://</code> protocol. E.g. <code class="literal">pact://http://localhost:8085</code></p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
||||
ids = "com.example:beer-api-producer-pact",
|
||||
repositoryRoot = "pact://http://localhost:8085")</span></em>
|
||||
repositoryRoot = "pact://http://localhost:8085")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BeerControllerTest {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//Inject the port of the running stub</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@StubRunnerPort("beer-api-producer-pact")</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> producerPort;
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StubRunnerPort("beer-api-producer-pact")</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> producerPort;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}</pre><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Pact files will be downloaded from the Pact Broker</li><li class="listitem">Spring Cloud Contract will convert the Pact files into stub definitions</li><li class="listitem">The stub servers will be started and fed with stubs</li></ul></div><p>For more information about Pact support you can go to
|
||||
the <a class="xref" href="multi__using_the_pluggable_architecture.html#pact-stub-downloader" title="10.7 Using the Pact Stub Downloader">Section 10.7, “Using the Pact Stub Downloader”</a> section.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_can_i_debug_the_requestresponse_being_sent_by_the_generated_tests_client" href="#_how_can_i_debug_the_requestresponse_being_sent_by_the_generated_tests_client"></a>3.8 How can I debug the request/response being sent by the generated tests client?</h2></div></div></div><p>The generated tests all boil down to RestAssured in some form or fashion which relies on <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/" target="_top">Apache HttpClient</a>. HttpClient has a facility called <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging" target="_top">wire logging</a> which logs the entire request and response to HttpClient. Spring Boot has a logging <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_top">common application property</a> for doing this sort of thing, just add this to your application properties</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.org.apache.http.wire</span>=DEBUG</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_debug_the_mappingrequestresponse_being_sent_by_wiremock" href="#_how_can_i_debug_the_mappingrequestresponse_being_sent_by_wiremock"></a>3.8.1 How can I debug the mapping/request/response being sent by WireMock?</h3></div></div></div><p>Starting from version <code class="literal">1.2.0</code> we turn on WireMock logging to
|
||||
|
||||
@@ -212,7 +212,7 @@ producer stubs.</p></td></tr></table></div><p>The producer would setup the contr
|
||||
structure in your stubs jar.</p><pre class="programlisting">└── META-INF
|
||||
└── com.example
|
||||
└── beer-api-producer-restdocs
|
||||
└── <span class="hl-number">2.0</span>.<span class="hl-number">0</span>
|
||||
└── <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
|
||||
├── contracts
|
||||
│ └── nested
|
||||
│ └── contract2.groovy
|
||||
@@ -229,12 +229,12 @@ the configuration files for the given HTTP server stub.</p><p>Spring Cloud Contr
|
||||
can extend, for WireMock - <code class="literal">org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStubConfigurer</code>. In the <code class="literal">configure</code> method
|
||||
you can provide your own, custom configuration for the given stub. The use
|
||||
case might be starting WireMock for the given artifact id, on an HTTPs port. Example:</p><p><b>WireMockHttpServerStubConfigurer implementation. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@CompileStatic</span></em>
|
||||
</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@CompileStatic</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HttpsForFraudDetection <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> WireMockHttpServerStubConfigurer {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Log log = LogFactory.getLog(HttpsForFraudDetection)
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
WireMockConfiguration configure(WireMockConfiguration httpStubConfiguration, HttpServerStubConfiguration httpServerStubConfiguration) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (httpServerStubConfiguration.stubConfiguration.artifactId == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> httpsPort = SocketUtils.findAvailableTcpPort()
|
||||
@@ -253,10 +253,10 @@ case might be starting WireMock for the given artifact id, on an HTTPs port. Exa
|
||||
(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: stubs)
|
||||
--maxPort, --maxp <Integer> Maximum port value to be assigned to
|
||||
the WireMock instance. Defaults to
|
||||
<span class="hl-number">15000</span> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: <span class="hl-number">15000</span>)
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">15000</xslthl:number> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">15000</xslthl:number>)
|
||||
--minPort, --minp <Integer> Minimum port value to be assigned to
|
||||
the WireMock instance. Defaults to
|
||||
<span class="hl-number">10000</span> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: <span class="hl-number">10000</span>)
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">10000</xslthl:number> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">10000</xslthl:number>)
|
||||
-p, --password Password to user when connecting to
|
||||
repository
|
||||
--phost, --proxyHost Proxy host to use <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> repository
|
||||
@@ -280,7 +280,7 @@ case might be starting WireMock for the given artifact id, on an HTTPs port. Exa
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/ping"</span>
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span>: {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span class="hl-number">200</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"pong"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span>: {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"text/plain"</span>
|
||||
@@ -288,13 +288,13 @@ case might be starting WireMock for the given artifact id, on an HTTPs port. Exa
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_viewing_registered_mappings" href="#_viewing_registered_mappings"></a>Viewing registered mappings</h4></div></div></div><p>Every stubbed collaborator exposes list of defined mappings under <code class="literal">__/admin/</code> endpoint.</p><p>You can also use the <code class="literal">mappingsOutputFolder</code> property to dump the mappings to files.
|
||||
For annotation based approach it would look like this</p><pre class="programlisting">@AutoConfigureStubRunner(ids=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a.b.c:loanIssuance,a.b.c:fraudDetectionServer"</span>,
|
||||
mappingsOutputFolder = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings/"</span>)</pre><p>and for the JUnit approach like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ClassRule</span></em> <em><span class="hl-annotation" style="color: gray">@Shared</span></em> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
|
||||
mappingsOutputFolder = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings/"</span>)</pre><p>and for the JUnit approach like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Shared</xslthl:annotation> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
|
||||
.repoRoot(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://some_url"</span>)
|
||||
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a.b.c"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)
|
||||
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a.b.c:fraudDetectionServer"</span>)
|
||||
.withMappingsOutputFolder(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings"</span>)</pre><p>Then if you check out the folder <code class="literal">target/outputmappings</code> you would see the following structure</p><pre class="programlisting">.
|
||||
├── fraudDetectionServer_<span class="hl-number">13705</span>
|
||||
└── loanIssuance_<span class="hl-number">12255</span></pre><p>That means that there were two stubs registered. <code class="literal">fraudDetectionServer</code> was registered at port <code class="literal">13705</code>
|
||||
├── fraudDetectionServer_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">13705</xslthl:number>
|
||||
└── loanIssuance_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">12255</xslthl:number></pre><p>That means that there were two stubs registered. <code class="literal">fraudDetectionServer</code> was registered at port <code class="literal">13705</code>
|
||||
and <code class="literal">loanIssuance</code> at port <code class="literal">12255</code>. If we take a look at one of the files we would see (for WireMock)
|
||||
mappings available for the given server:</p><pre class="programlisting">[<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"f9152eb9-bf77-4c38-8289-90be7d10d0d7"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
@@ -303,13 +303,13 @@ mappings available for the given server:</p><pre class="programlisting">[<span x
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"GET"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uuid"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"f9152eb9-bf77-4c38-8289-90be7d10d0d7"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
...
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_messaging_stubs" href="#_messaging_stubs"></a>Messaging Stubs</h4></div></div></div><p>Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.</p></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_junit_rule_and_stub_runner_junit5_extension" href="#_stub_runner_junit_rule_and_stub_runner_junit5_extension"></a>6.4 Stub Runner JUnit Rule and Stub Runner JUnit5 Extension</h2></div></div></div><p>Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ClassRule</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_messaging_stubs" href="#_messaging_stubs"></a>Messaging Stubs</h4></div></div></div><p>Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.</p></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_junit_rule_and_stub_runner_junit5_extension" href="#_stub_runner_junit_rule_and_stub_runner_junit5_extension"></a>6.4 Stub Runner JUnit Rule and Stub Runner JUnit5 Extension</h2></div></div></div><p>Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule().repoRoot(repoRoot())
|
||||
.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
|
||||
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>,
|
||||
@@ -317,8 +317,8 @@ mappings available for the given server:</p><pre class="programlisting">[<span x
|
||||
.downloadStub(
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@BeforeClass</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AfterClass</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@BeforeClass</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AfterClass</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setupProps() {
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.repository.root"</span>);
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.classifier"</span>);
|
||||
@@ -332,14 +332,14 @@ Check their <a class="link" href="https://wiki.eclipse.org/Aether" target="_top"
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Contract for finding registered stubs.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StubFinder <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> StubTrigger {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* For the given groupId and artifactId tries to find the matching URL of the running
|
||||
* stub.
|
||||
* @param groupId - might be null. In that case a search only via artifactId takes
|
||||
@@ -347,31 +347,31 @@ Check their <a class="link" href="https://wiki.eclipse.org/Aether" target="_top"
|
||||
* @param artifactId - artifact id of the stub
|
||||
* @return URL of a running stub or throws exception if not found
|
||||
* @throws StubNotFoundException in case of not finding a stub
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
URL findStubUrl(String groupId, String artifactId) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> StubNotFoundException;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* For the given Ivy notation {@code [groupId]:artifactId:[version]:[classifier]}
|
||||
* tries to find the matching URL of the running stub. You can also pass only
|
||||
* {@code artifactId}.
|
||||
* @param ivyNotation - Ivy representation of the Maven artifact
|
||||
* @return URL of a running stub or throws exception if not found
|
||||
* @throws StubNotFoundException in case of not finding a stub
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
URL findStubUrl(String ivyNotation) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> StubNotFoundException;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* @return all running stubs
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
RunningStubs findAllRunningStubs();
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* @return the list of Contracts
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
Map<StubConfiguration, Collection<Contract>> getContracts();
|
||||
|
||||
}</pre><p>Example of usage in Spock tests:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ClassRule</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Shared</span></em>
|
||||
}</pre><p>Example of usage in Spock tests:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Shared</xslthl:annotation>
|
||||
StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
|
||||
.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
|
||||
.repoRoot(StubRunnerRuleSpec.getResource(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/m2repo/repository"</span>).toURI().toString())
|
||||
@@ -400,7 +400,7 @@ def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should outp
|
||||
def url = rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>)
|
||||
then:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> File(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappingsforrule"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer_${url.port}"</span>).exists()
|
||||
}</pre><p>Example of usage in JUnit tests:</p><pre class="programlisting"> <em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
}</pre><p>Example of usage in JUnit tests:</p><pre class="programlisting"> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> should_start_wiremock_servers() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// expect: 'WireMocks are running'</span>
|
||||
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>,
|
||||
@@ -433,7 +433,7 @@ def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should outp
|
||||
}
|
||||
|
||||
}</pre><p>JUnit 5 Extension example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Visible for Junit</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@RegisterExtension</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RegisterExtension</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> StubRunnerExtension stubRunnerExtension = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerExtension()
|
||||
.repoRoot(repoRoot()).stubsMode(StubRunnerProperties.StubsMode.REMOTE)
|
||||
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>,
|
||||
@@ -442,8 +442,8 @@ def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should outp
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>)
|
||||
.withMappingsOutputFolder(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappingsforrule"</span>);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@BeforeAll</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AfterAll</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@BeforeAll</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AfterAll</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setupProps() {
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.repository.root"</span>);
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.classifier"</span>);
|
||||
@@ -461,16 +461,16 @@ def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should outp
|
||||
<code class="literal">MessageVerifier</code> interface to the rule builder (e.g. <code class="literal">rule.messageVerifier(new MyMessageVerifier())</code>).
|
||||
If you don’t do this, then whenever you try to send a message an exception will be thrown.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_maven_settings" href="#_maven_settings"></a>6.4.1 Maven settings</h3></div></div></div><p>The stub downloader honors Maven settings for a different local repository folder.
|
||||
Authentication details for repositories and profiles are currently not taken into account, so you need to specify it using the properties mentioned above.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_providing_fixed_ports" href="#_providing_fixed_ports"></a>6.4.2 Providing fixed ports</h3></div></div></div><p>You can also run your stubs on fixed ports. You can do it in two different ways. One is to pass it in the properties, and the other via fluent API of
|
||||
JUnit rule.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_fluent_api" href="#_fluent_api"></a>6.4.3 Fluent API</h3></div></div></div><p>When using the <code class="literal">StubRunnerRule</code> or <code class="literal">StubRunnerExtension</code> you can add a stub to download and then pass the port for the last downloaded stub.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ClassRule</span></em>
|
||||
JUnit rule.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_fluent_api" href="#_fluent_api"></a>6.4.3 Fluent API</h3></div></div></div><p>When using the <code class="literal">StubRunnerRule</code> or <code class="literal">StubRunnerExtension</code> you can add a stub to download and then pass the port for the last downloaded stub.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule().repoRoot(repoRoot())
|
||||
.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
|
||||
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)
|
||||
.withPort(<span class="hl-number">12345</span>).downloadStub(
|
||||
.withPort(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">12345</xslthl:number>).downloadStub(
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346"</span>);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@BeforeClass</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AfterClass</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@BeforeClass</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AfterClass</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setupProps() {
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.repository.root"</span>);
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.classifier"</span>);
|
||||
@@ -479,28 +479,28 @@ JUnit rule.</p></div><div class="section"><div class="titlepage"><div><div><h3 c
|
||||
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>))
|
||||
.isEqualTo(URI.create(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:12346"</span>).toURL());</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stub_runner_with_spring" href="#_stub_runner_with_spring"></a>6.4.4 Stub Runner with Spring</h3></div></div></div><p>Sets up Spring configuration of the Stub Runner project.</p><p>By providing a list of stubs inside your configuration file the Stub Runner automatically downloads
|
||||
and registers in WireMock the selected stubs.</p><p>If you want to find the URL of your stubbed dependency you can autowire the <code class="literal">StubFinder</code> interface and use
|
||||
its methods as presented below:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(properties = [" stubrunner.cloud.enabled=false",
|
||||
its methods as presented below:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(properties = [" stubrunner.cloud.enabled=false",
|
||||
'foo=${stubrunner.runningstubs.fraudDetectionServer.port}',
|
||||
'fooWithGroup=${stubrunner.runningstubs.org.springframework.cloud.contract.verifier.stubs.fraudDetectionServer.port}'])</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
|
||||
httpServerStubConfigurer = HttpsForFraudDetection)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ActiveProfiles("test")</span></em>
|
||||
'fooWithGroup=${stubrunner.runningstubs.org.springframework.cloud.contract.verifier.stubs.fraudDetectionServer.port}'])</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
|
||||
httpServerStubConfigurer = HttpsForFraudDetection)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ActiveProfiles("test")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerConfigurationSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
StubFinder stubFinder
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
Environment environment
|
||||
<em><span class="hl-annotation" style="color: gray">@StubRunnerPort("fraudDetectionServer")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StubRunnerPort("fraudDetectionServer")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> fraudDetectionServerPort
|
||||
<em><span class="hl-annotation" style="color: gray">@StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> fraudDetectionServerPortWithGroupId
|
||||
<em><span class="hl-annotation" style="color: gray">@Value('${foo}')</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Value('${foo}')</xslthl:annotation>
|
||||
Integer foo
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@BeforeClass</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AfterClass</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@BeforeClass</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AfterClass</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setupProps() {
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.repository.root"</span>)
|
||||
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.classifier"</span>)
|
||||
@@ -552,18 +552,18 @@ its methods as presented below:</p><pre class="programlisting"><em><span class="
|
||||
given:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> fraudPort = stubFinder.findAllRunningStubs().getPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>)
|
||||
expect:
|
||||
fraudPort > <span class="hl-number">0</span>
|
||||
fraudPort > <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
|
||||
environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>, Integer) == fraudPort
|
||||
environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fooWithGroup"</span>, Integer) == fraudPort
|
||||
foo == fraudPort
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Issue("#573")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Issue("#573")</xslthl:annotation>
|
||||
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should be able to retrieve the port of a running stub via an annotation'</span>() {
|
||||
given:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> fraudPort = stubFinder.findAllRunningStubs().getPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>)
|
||||
expect:
|
||||
fraudPort > <span class="hl-number">0</span>
|
||||
fraudPort > <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
|
||||
fraudDetectionServerPort == fraudPort
|
||||
fraudDetectionServerPortWithGroupId == fraudPort
|
||||
}
|
||||
@@ -575,16 +575,16 @@ its methods as presented below:</p><pre class="programlisting"><em><span class="
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> File(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings/"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer_${url.port}"</span>).exists()
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Config {}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@CompileStatic</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@CompileStatic</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HttpsForFraudDetection <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> WireMockHttpServerStubConfigurer {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Log log = LogFactory.getLog(HttpsForFraudDetection)
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
WireMockConfiguration configure(WireMockConfiguration httpStubConfiguration, HttpServerStubConfiguration httpServerStubConfiguration) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (httpServerStubConfiguration.stubConfiguration.artifactId == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> httpsPort = SocketUtils.findAvailableTcpPort()
|
||||
@@ -611,9 +611,9 @@ Below you can find an example of achieving the same result by setting values on
|
||||
for every registered WireMock server. Example for Stub Runner ids
|
||||
<code class="literal">com.example:foo</code>, <code class="literal">com.example:bar</code>.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">stubrunner.runningstubs.foo.port</code></li><li class="listitem"><code class="literal">stubrunner.runningstubs.com.example.foo.port</code></li><li class="listitem"><code class="literal">stubrunner.runningstubs.bar.port</code></li><li class="listitem"><code class="literal">stubrunner.runningstubs.com.example.bar.port</code></li></ul></div><p>Which you can reference in your code.</p><p>You can also use the <code class="literal">@StubRunnerPort</code> annotation to inject the port of a running stub.
|
||||
Value of the annotation can be the <code class="literal">groupid:artifactid</code> or just the <code class="literal">artifactid</code>. Example for Stub Runner ids
|
||||
<code class="literal">com.example:foo</code>, <code class="literal">com.example:bar</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@StubRunnerPort("foo")</span></em>
|
||||
<code class="literal">com.example:foo</code>, <code class="literal">com.example:bar</code>.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StubRunnerPort("foo")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> fooPort;
|
||||
<em><span class="hl-annotation" style="color: gray">@StubRunnerPort("com.example:bar")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StubRunnerPort("com.example:bar")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> barPort;</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_spring_cloud" href="#_stub_runner_spring_cloud"></a>6.5 Stub Runner Spring Cloud</h2></div></div></div><p>Stub Runner can integrate with Spring Cloud.</p><p>For real life examples you can check the</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.1.x/producer" target="_top">producer app sample</a></li><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.1.x/consumer_with_discovery" target="_top">consumer app sample</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stubbing_service_discovery" href="#_stubbing_service_discovery"></a>6.5.1 Stubbing Service Discovery</h3></div></div></div><p>The most important feature of <code class="literal">Stub Runner Spring Cloud</code> is the fact that it’s stubbing</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">DiscoveryClient</code></li><li class="listitem"><code class="literal">Ribbon</code> <code class="literal">ServerList</code></li></ul></div><p>that means that regardless of the fact whether you’re using Zookeeper, Consul, Eureka or anything else, you don’t need that in your tests.
|
||||
We’re starting WireMock instances of your dependencies and we’re telling your application whenever you’re using <code class="literal">Feign</code>, load balanced <code class="literal">RestTemplate</code>
|
||||
or <code class="literal">DiscoveryClient</code> directly, to call those stubbed servers instead of calling the real Service Discovery tool.</p><p>For example this test will pass</p><pre class="programlisting">def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should make service discovery work'</span>() {
|
||||
@@ -652,12 +652,12 @@ or a subdirectory called <code class="literal">config</code> or in <code class="
|
||||
ids:
|
||||
- com.example:beer-api-producer:+:9876</pre><p>
|
||||
</p><p>and then just call <code class="literal">spring cloud stubrunner</code> from your terminal window to start
|
||||
the Stub Runner server. It will be available at port <code class="literal">8750</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_endpoints" href="#_endpoints"></a>6.6.2 Endpoints</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_http" href="#_http"></a>HTTP</h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">GET <code class="literal">/stubs</code> - returns a list of all running stubs in <code class="literal">ivy:integer</code> notation</li><li class="listitem">GET <code class="literal">/stubs/{ivy}</code> - returns a port for the given <code class="literal">ivy</code> notation (when calling the endpoint <code class="literal">ivy</code> can also be <code class="literal">artifactId</code> only)</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_messaging" href="#_messaging"></a>Messaging</h4></div></div></div><p>For Messaging</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">GET <code class="literal">/triggers</code> - returns a list of all running labels in <code class="literal">ivy : [ label1, label2 …​]</code> notation</li><li class="listitem">POST <code class="literal">/triggers/{label}</code> - executes a trigger with <code class="literal">label</code></li><li class="listitem">POST <code class="literal">/triggers/{ivy}/{label}</code> - executes a trigger with <code class="literal">label</code> for the given <code class="literal">ivy</code> notation (when calling the endpoint <code class="literal">ivy</code> can also be <code class="literal">artifactId</code> only)</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example" href="#_example"></a>6.6.3 Example</h3></div></div></div><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ContextConfiguration(classes = StubRunnerBoot, loader = SpringBootContextLoader)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(properties = "spring.cloud.zookeeper.enabled=false")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ActiveProfiles("test")</span></em>
|
||||
the Stub Runner server. It will be available at port <code class="literal">8750</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_endpoints" href="#_endpoints"></a>6.6.2 Endpoints</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_http" href="#_http"></a>HTTP</h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">GET <code class="literal">/stubs</code> - returns a list of all running stubs in <code class="literal">ivy:integer</code> notation</li><li class="listitem">GET <code class="literal">/stubs/{ivy}</code> - returns a port for the given <code class="literal">ivy</code> notation (when calling the endpoint <code class="literal">ivy</code> can also be <code class="literal">artifactId</code> only)</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_messaging" href="#_messaging"></a>Messaging</h4></div></div></div><p>For Messaging</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">GET <code class="literal">/triggers</code> - returns a list of all running labels in <code class="literal">ivy : [ label1, label2 …​]</code> notation</li><li class="listitem">POST <code class="literal">/triggers/{label}</code> - executes a trigger with <code class="literal">label</code></li><li class="listitem">POST <code class="literal">/triggers/{ivy}/{label}</code> - executes a trigger with <code class="literal">label</code> for the given <code class="literal">ivy</code> notation (when calling the endpoint <code class="literal">ivy</code> can also be <code class="literal">artifactId</code> only)</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example" href="#_example"></a>6.6.3 Example</h3></div></div></div><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = StubRunnerBoot, loader = SpringBootContextLoader)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(properties = "spring.cloud.zookeeper.enabled=false")</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ActiveProfiles("test")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerBootSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
StubRunning stubRunning
|
||||
|
||||
def setup() {
|
||||
@@ -677,8 +677,8 @@ the Stub Runner server. It will be available at port <code class="literal">8750<
|
||||
when:
|
||||
def response = RestAssuredMockMvc.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/stubs/${stubId}"</span>)
|
||||
then:
|
||||
response.statusCode == <span class="hl-number">200</span>
|
||||
Integer.valueOf(response.body.asString()) > <span class="hl-number">0</span>
|
||||
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
Integer.valueOf(response.body.asString()) > <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
|
||||
where:
|
||||
stubId << [<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:+:stubs'</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'</span>,
|
||||
@@ -691,7 +691,7 @@ the Stub Runner server. It will be available at port <code class="literal">8750<
|
||||
when:
|
||||
def response = RestAssuredMockMvc.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/stubs/a:b:c:d"</span>)
|
||||
then:
|
||||
response.statusCode == <span class="hl-number">404</span>
|
||||
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>
|
||||
}
|
||||
|
||||
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should return a list of messaging labels that can be triggered when version and classifier are passed'</span>() {
|
||||
@@ -709,9 +709,9 @@ the Stub Runner server. It will be available at port <code class="literal">8750<
|
||||
when:
|
||||
def response = RestAssuredMockMvc.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/triggers/delete_book"</span>)
|
||||
then:
|
||||
response.statusCode == <span class="hl-number">200</span>
|
||||
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
and:
|
||||
<span class="hl-number">1</span> * stubRunning.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete_book'</span>)
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number> * stubRunning.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete_book'</span>)
|
||||
}
|
||||
|
||||
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should trigger a messaging label for a stub with [#stubId] ivy notation'</span>() {
|
||||
@@ -721,9 +721,9 @@ the Stub Runner server. It will be available at port <code class="literal">8750<
|
||||
when:
|
||||
def response = RestAssuredMockMvc.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/triggers/$stubId/delete_book"</span>)
|
||||
then:
|
||||
response.statusCode == <span class="hl-number">200</span>
|
||||
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
and:
|
||||
<span class="hl-number">1</span> * stubRunning.trigger(stubId, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete_book'</span>)
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number> * stubRunning.trigger(stubId, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete_book'</span>)
|
||||
where:
|
||||
stubId << [<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bootService'</span>]
|
||||
}
|
||||
@@ -748,10 +748,10 @@ the Stub Runner server. It will be available at port <code class="literal">8750<
|
||||
of testing scenarios.</p><p>The problem with this approach is such that if you’re doing microservices most likely you’re
|
||||
using a service discovery tool. Stub Runner Boot allows you to solve this issue by starting the
|
||||
required stubs and register them in a service discovery tool. Let’s take a look at an example of
|
||||
such a setup with Eureka. Let’s assume that Eureka was already running.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableStubRunnerServer</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableEurekaClient</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner</span></em>
|
||||
such a setup with Eureka. Let’s assume that Eureka was already running.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootApplication</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableStubRunnerServer</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableEurekaClient</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerBootEurekaExample {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
|
||||
@@ -761,17 +761,17 @@ the Stub Runner server. It will be available at port <code class="literal">8750<
|
||||
}</pre><p>As you can see we want to start a Stub Runner Boot server <code class="literal">@EnableStubRunnerServer</code>, enable Eureka client <code class="literal">@EnableEurekaClient</code>
|
||||
and we want to have the stub runner feature turned on <code class="literal">@AutoConfigureStubRunner</code>.</p><p>Now let’s assume that we want to start this application so that the stubs get automatically registered.
|
||||
We can do it by running the app <code class="literal">java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar</code> where
|
||||
<code class="literal">${SYSTEM_PROPS}</code> would contain the following list of properties</p><pre class="programlisting">* -Dstubrunner.repositoryRoot=https://repo.spring.io/snapshot (<span class="hl-number">1</span>)
|
||||
* -Dstubrunner.cloud.stubbed.discovery.enabled=false (<span class="hl-number">2</span>)
|
||||
<code class="literal">${SYSTEM_PROPS}</code> would contain the following list of properties</p><pre class="programlisting">* -Dstubrunner.repositoryRoot=https://repo.spring.io/snapshot (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>)
|
||||
* -Dstubrunner.cloud.stubbed.discovery.enabled=false (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>)
|
||||
* -Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.
|
||||
* springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.
|
||||
* cloud.contract.verifier.stubs:bootService (<span class="hl-number">3</span>)
|
||||
* cloud.contract.verifier.stubs:bootService (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>)
|
||||
* -Dstubrunner.idsToServiceIds.fraudDetectionServer=
|
||||
* someNameThatShouldMapFraudDetectionServer (<span class="hl-number">4</span>)
|
||||
* someNameThatShouldMapFraudDetectionServer (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>)
|
||||
*
|
||||
* (<span class="hl-number">1</span>) - we tell Stub Runner where all the stubs reside (<span class="hl-number">2</span>) - we don<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'t want the default
|
||||
* (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>) - we tell Stub Runner where all the stubs reside (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>) - we don<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'t want the default
|
||||
* behaviour where the discovery service is stubbed. That'</span>s why the stub registration will
|
||||
* be picked (<span class="hl-number">3</span>) - we provide a list of stubs to download (<span class="hl-number">4</span>) - we provide a list of</pre><p>That way your deployed application can send requests to started WireMock servers via the service
|
||||
* be picked (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>) - we provide a list of stubs to download (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>) - we provide a list of</pre><p>That way your deployed application can send requests to started WireMock servers via the service
|
||||
discovery. Most likely points 1-3 could be set by default in <code class="literal">application.yml</code> cause they are not
|
||||
likely to change. That way you can provide only the list of stubs to download whenever you start
|
||||
the Stub Runner Boot.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stubs_per_consumer" href="#_stubs_per_consumer"></a>6.7 Stubs Per Consumer</h2></div></div></div><p>There are cases in which 2 consumers of the same endpoint want to have 2 different responses.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>This approach also allows you to immediately know which consumer is using which part of your API.
|
||||
@@ -807,22 +807,22 @@ if it contains the subfolder with name of the consumer in the path only then wil
|
||||
└── foo-consumer
|
||||
├── bookReturnedForFoo.groovy
|
||||
└── shouldCallFoo.groovy</pre><p>Being the <code class="literal">bar-consumer</code> consumer you can either set the <code class="literal">spring.application.name</code> or the <code class="literal">stubrunner.consumer-name</code> to <code class="literal">bar-consumer</code>
|
||||
Or set the test as follows:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(properties = ["spring.application.name=bar-consumer"])</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
|
||||
Or set the test as follows:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(properties = ["spring.application.name=bar-consumer"])</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
|
||||
repositoryRoot = "classpath:m2repo/repository/",
|
||||
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
||||
stubsPerConsumer = true)</span></em>
|
||||
stubsPerConsumer = true)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerStubsPerConsumerSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
|
||||
...
|
||||
}</pre><p>Then only the stubs registered under a path that contains the <code class="literal">bar-consumer</code> in its name (i.e. those from the
|
||||
<code class="literal">src/test/resources/contracts/bar-consumer/some/contracts/…​</code> folder) will be allowed to be referenced.</p><p>Or set the consumer name explicitly</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
|
||||
<code class="literal">src/test/resources/contracts/bar-consumer/some/contracts/…​</code> folder) will be allowed to be referenced.</p><p>Or set the consumer name explicitly</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
|
||||
repositoryRoot = "classpath:m2repo/repository/",
|
||||
consumerName = "foo-consumer",
|
||||
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
||||
stubsPerConsumer = true)</span></em>
|
||||
stubsPerConsumer = true)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerStubsPerConsumerWithConsumerNameSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
|
||||
...
|
||||
}</pre><p>Then only the stubs registered under a path that contains the <code class="literal">foo-consumer</code> in its name (i.e. those from the
|
||||
@@ -860,9 +860,9 @@ $ STUBRUNNER_REPOSITORY_ROOT=<span xmlns:d="http://docbook.org/ns/docbook" class
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Run the docker with Stub Runner Boot</span>
|
||||
$ docker run --rm -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_IDS=${STUBRUNNER_IDS}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_REPOSITORY_ROOT=${STUBRUNNER_REPOSITORY_ROOT}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_STUBS_MODE=REMOTE"</span> -p <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${STUBRUNNER_PORT}:${STUBRUNNER_PORT}"</span> -p <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"9876:9876"</span> springcloud/spring-cloud-contract-stub-runner:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${SC_CONTRACT_DOCKER_VERSION}"</span></pre><p>What’s happening is that</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">a standalone Stub Runner application got started</li><li class="listitem">it downloaded the stub with coordinates <code class="literal">com.example:bookstore:0.0.1.RELEASE:stubs</code> on port <code class="literal">9876</code></li><li class="listitem">it got downloaded from Artifactory running at <code class="literal"><a class="link" href="http://192.168.0.100:8081/artifactory/libs-release-local" target="_top">http://192.168.0.100:8081/artifactory/libs-release-local</a></code></li><li class="listitem">after a while Stub Runner will be running on port <code class="literal">8083</code></li><li class="listitem">and the stubs will be running at port <code class="literal">9876</code></li></ul></div><p>On the server side we built a stateful stub. Let’s use curl to assert
|
||||
that the stubs are setup properly.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># let's execute the first request (no response is returned)</span>
|
||||
$ curl -H <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type:application/json"</span> -X POST --data <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }'</span> http://localhost:<span class="hl-number">9876</span>/api/books
|
||||
$ curl -H <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type:application/json"</span> -X POST --data <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }'</span> http://localhost:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9876</xslthl:number>/api/books
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Now time for the second request</span>
|
||||
$ curl -X GET http://localhost:<span class="hl-number">9876</span>/api/books
|
||||
$ curl -X GET http://localhost:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9876</xslthl:number>/api/books
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># You will receive contents of the JSON</span></pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you want use the stubs that you have built locally, on your host,
|
||||
then you should pass the environment variable <code class="literal">-e STUBRUNNER_STUBS_MODE=LOCAL</code> and mount
|
||||
the volume of your local m2 <code class="literal">-v "${HOME}/.m2/:/root/.m2:ro"</code></p></td></tr></table></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_messaging.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi_stub-runner-for-messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Spring Cloud Contract Verifier Messaging </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Stub Runner for Messaging</td></tr></table></div></body></html>
|
||||
@@ -65,10 +65,10 @@ Stub Runner</code> properties, as shown in the following example:</p><pre class=
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ids</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'com.example:http-server-dsl:+:stubs:8080'</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> repositoryRoot</span>: https://repo.spring.io/libs-snapshot</pre></li></ul></div><p>Now you can annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation,
|
||||
provide the <code class="literal">group-id</code> and <code class="literal">artifact-id</code> values for <code class="literal">Spring Cloud Contract Stub Runner</code> to
|
||||
run the collaborators' stubs for you, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment=WebEnvironment.NONE)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
|
||||
stubsMode = StubRunnerProperties.StubsMode.LOCAL)</span></em>
|
||||
run the collaborators' stubs for you, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment=WebEnvironment.NONE)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
|
||||
stubsMode = StubRunnerProperties.StubsMode.LOCAL)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Use the <code class="literal">REMOTE</code> <code class="literal">stubsMode</code> when downloading stubs from an online repository and
|
||||
<code class="literal">LOCAL</code> for offline work.</p></td></tr></table></div><p>Now, in your integration test, you can receive stubbed versions of HTTP responses or
|
||||
messages that are expected to be emitted by the collaborator service.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="spring-cloud-contract-verifier-intro-three-minute-tour" href="#spring-cloud-contract-verifier-intro-three-minute-tour"></a>2.4.2 A Three-minute Tour</h3></div></div></div><p>This brief tour walks through using Spring Cloud Contract:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_introduction.html#spring-cloud-contract-verifier-intro-three-minute-tour-producer" title="On the Producer Side">the section called “On the Producer Side”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_introduction.html#spring-cloud-contract-verifier-intro-three-minute-tour-consumer" title="On the Consumer Side">the section called “On the Consumer Side”</a></li></ul></div><p>You can find an even more brief tour
|
||||
@@ -84,7 +84,7 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/fraudcheck'</span>
|
||||
body([
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"client.id"</span>: $(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{10}'</span>)),
|
||||
loanAmount: <span class="hl-number">99999</span>
|
||||
loanAmount: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
|
||||
])
|
||||
headers {
|
||||
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
|
||||
@@ -104,8 +104,8 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> method</span>: PUT
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> url</span>: /fraudcheck
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> body</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> "client.id"</span>: <span class="hl-number">1234567890</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> loanAmount</span>: <span class="hl-number">99999</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> "client.id"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1234567890</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> loanAmount</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> headers</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> Content-Type</span>: application/json
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> matchers</span>:
|
||||
@@ -114,12 +114,12 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> type</span>: by_regex
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> value</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{10}"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">response</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> status</span>: <span class="hl-number">200</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> status</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> body</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> fraudCheckStatus</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> "rejection.reason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> headers</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> Content-Type</span>: application/json;charset=UTF-<span class="hl-number">8</span></pre><p>In the case of messaging, you can define:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The input and the output messages can be defined (taking into account from and where it
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> Content-Type</span>: application/json;charset=UTF-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8</xslthl:number></pre><p>In the case of messaging, you can define:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The input and the output messages can be defined (taking into account from and where it
|
||||
was sent, the message body, and the header).</li><li class="listitem">The methods that should be called after the message is received.</li><li class="listitem">The methods that, when called, should trigger a message.</li></ul></div><p>The following example shows a Camel messaging contract expressed in Groovy DSL:</p><pre class="programlisting"> def contractDsl = Contract.make {
|
||||
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
|
||||
input {
|
||||
@@ -152,7 +152,7 @@ portion of the file:</p><pre class="programlisting"><span xmlns:d="http://docboo
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><extensions></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></extensions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>Running <code class="literal">./mvnw clean install</code> automatically generates tests that verify the application
|
||||
compliance with the added contracts. By default, the generated tests are under
|
||||
<code class="literal">org.springframework.cloud.contract.verifier.tests.</code>.</p><p>The following example shows a sample auto-generated test for an HTTP contract:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<code class="literal">org.springframework.cloud.contract.verifier.tests.</code>.</p><p>The following example shows a sample auto-generated test for an HTTP contract:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
@@ -164,7 +164,7 @@ compliance with the added contracts. By default, the generated tests are under
|
||||
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1.json.*"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
@@ -213,18 +213,18 @@ contain all the setup necessary to run them (for example, <code class="literal">
|
||||
setup or messaging test setup).</p><p>Once the implementation and the test base class are in place, the tests pass, and both the
|
||||
application and the stub artifacts are built and installed in the local Maven repository.
|
||||
Information about installing the stubs jar to the local repository appears in the logs, as
|
||||
shown in the following example:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<span class="hl-number">1.0</span>.<span class="hl-number">0.</span>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
shown in the following example:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
[INFO]
|
||||
[INFO] --- maven-jar-plugin:<span class="hl-number">2.6</span>:jar (default-jar) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.jar
|
||||
[INFO] --- maven-jar-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.6</xslthl:number>:jar (default-jar) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar
|
||||
[INFO]
|
||||
[INFO] --- spring-boot-maven-plugin:<span class="hl-number">1.5</span>.<span class="hl-number">5.</span>BUILD-SNAPSHOT:repackage (default) @ http-server ---
|
||||
[INFO] --- spring-boot-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5.</xslthl:number>BUILD-SNAPSHOT:repackage (default) @ http-server ---
|
||||
[INFO]
|
||||
[INFO] --- maven-install-plugin:<span class="hl-number">2.5</span>.<span class="hl-number">2</span>:install (default-install) @ http-server ---
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.jar
|
||||
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar</pre><p>You can now merge the changes and publish both the application and the stub artifacts
|
||||
[INFO] --- maven-install-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>:install (default-install) @ http-server ---
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar
|
||||
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar</pre><p>You can now merge the changes and publish both the application and the stub artifacts
|
||||
in an online repository.</p><p><span class="strong"><strong>Docker Project</strong></span></p><p>In order to enable working with contracts while creating applications in non-JVM
|
||||
technologies, the <code class="literal">springcloud/spring-cloud-contract</code> Docker image has been created. It
|
||||
contains a project that automatically generates tests for HTTP contracts and executes them
|
||||
@@ -245,20 +245,20 @@ Runner</code> properties, as shown in the following example:</p><pre class="prog
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ids</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'com.example:http-server-dsl:+:stubs:8080'</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> repositoryRoot</span>: https://repo.spring.io/libs-snapshot</pre></li></ul></div><p>Now you can annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation,
|
||||
provide the <code class="literal">group-id</code> and <code class="literal">artifact-id</code> for <code class="literal">Spring Cloud Contract Stub Runner</code> to run
|
||||
the collaborators' stubs for you, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment=WebEnvironment.NONE)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
|
||||
stubsMode = StubRunnerProperties.StubsMode.LOCAL)</span></em>
|
||||
the collaborators' stubs for you, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment=WebEnvironment.NONE)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
|
||||
stubsMode = StubRunnerProperties.StubsMode.LOCAL)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Use the <code class="literal">REMOTE</code> <code class="literal">stubsMode</code> when downloading stubs from an online repository and
|
||||
<code class="literal">LOCAL</code> for offline work.</p></td></tr></table></div><p>In your integration test, you can receive stubbed versions of HTTP responses or messages
|
||||
that are expected to be emitted by the collaborator service. You can see entries similar
|
||||
to the following in the build logs:</p><pre class="programlisting"><span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.403</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.438</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved version is <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.439</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolving artifact com.example:http-server:jar:stubs:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT using remote repositories []
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.451</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved artifact com.example:http-server:jar:stubs:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.465</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar]
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.475</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacked file to [/var/folders/<span class="hl-number">0</span>p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">27.737</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.StubRunnerExecutor : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT:stubs=<span class="hl-number">8080</span>}]</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_defining_the_contract" href="#_defining_the_contract"></a>2.4.3 Defining the Contract</h3></div></div></div><p>As consumers of services, we need to define what exactly we want to achieve. We need to
|
||||
to the following in the build logs:</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.403</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.438</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved version is <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.439</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolving artifact com.example:http-server:jar:stubs:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT using remote repositories []
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.451</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved artifact com.example:http-server:jar:stubs:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.465</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar]
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.475</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacked file to [/var/folders/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">27.737</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.StubRunnerExecutor : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT:stubs=<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8080</xslthl:number>}]</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_defining_the_contract" href="#_defining_the_contract"></a>2.4.3 Defining the Contract</h3></div></div></div><p>As consumers of services, we need to define what exactly we want to achieve. We need to
|
||||
formulate our expectations. That is why we write contracts.</p><p>Assume that you want to send a request containing the ID of a client company and the
|
||||
amount it wants to borrow from us. You also want to send it to the /fraudcheck url via
|
||||
the PUT method.</p><p><b>Groovy DSL. </b>
|
||||
@@ -286,7 +286,7 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/fraudcheck'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (3)</span>
|
||||
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (4)</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"client.id"</span>: $(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{10}'</span>)),
|
||||
loanAmount : <span class="hl-number">99999</span>
|
||||
loanAmount : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
|
||||
])
|
||||
headers { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (5)</span>
|
||||
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
|
||||
@@ -392,16 +392,16 @@ response: # (7)
|
||||
You get a running WireMock instance/Messaging route that simulates the service.
|
||||
You would like to feed that instance with a proper stub definition.</p><p>At some point in time, you need to send a request to the Fraud Detection service.</p><pre class="programlisting">ResponseEntity<FraudServiceResponse> response = restTemplate.exchange(
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span> + port + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>, HttpMethod.PUT,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpEntity<>(request, httpHeaders), FraudServiceResponse.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);</pre><p>Annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation provide the group id and artifact id for the Stub Runner to download stubs of your collaborators.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(ids = {
|
||||
"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpEntity<>(request, httpHeaders), FraudServiceResponse.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);</pre><p>Annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation provide the group id and artifact id for the Stub Runner to download stubs of your collaborators.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = {
|
||||
"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><p>After that, during the tests, Spring Cloud Contract automatically finds the stubs
|
||||
(simulating the real service) in the Maven repository and exposes them on a configured
|
||||
(or random) port.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_server_side" href="#_server_side"></a>2.4.5 Server Side</h3></div></div></div><p>Since you are developing your stub, you need to be sure that it actually resembles your
|
||||
concrete implementation. You cannot have a situation where your stub acts in one way and
|
||||
your application behaves in a different way, especially in production.</p><p>To ensure that your application behaves the way you define in your stub, tests are
|
||||
generated from the stub you provide.</p><p>The autogenerated test looks, more or less, like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
generated from the stub you provide.</p><p>The autogenerated test looks, more or less, like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
@@ -413,7 +413,7 @@ generated from the stub you provide.</p><p>The autogenerated test looks, more or
|
||||
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1.json.*"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
@@ -490,11 +490,11 @@ following section to your build:</p><p class="primary"><b>Maven. </b>
|
||||
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/milestone"</span> }
|
||||
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/release"</span> }
|
||||
}</pre><p class="secondary">
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_side_loan_issuance" href="#_consumer_side_loan_issuance"></a>2.5.2 Consumer side (Loan Issuance)</h3></div></div></div><p>As a developer of the Loan Issuance service (a consumer of the Fraud Detection server), you might do the following steps:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">Start doing TDD by writing a test for your feature.</li><li class="listitem">Write the missing implementation.</li><li class="listitem">Clone the Fraud Detection service repository locally.</li><li class="listitem">Define the contract locally in the repo of Fraud Detection service.</li><li class="listitem">Add the Spring Cloud Contract Verifier plugin.</li><li class="listitem">Run the integration tests.</li><li class="listitem">File a pull request.</li><li class="listitem">Create an initial implementation.</li><li class="listitem">Take over the pull request.</li><li class="listitem">Write the missing implementation.</li><li class="listitem">Deploy your app.</li><li class="listitem">Work online.</li></ol></div><p><span class="strong"><strong>Start doing TDD by writing a test for your feature.</strong></span></p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_side_loan_issuance" href="#_consumer_side_loan_issuance"></a>2.5.2 Consumer side (Loan Issuance)</h3></div></div></div><p>As a developer of the Loan Issuance service (a consumer of the Fraud Detection server), you might do the following steps:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">Start doing TDD by writing a test for your feature.</li><li class="listitem">Write the missing implementation.</li><li class="listitem">Clone the Fraud Detection service repository locally.</li><li class="listitem">Define the contract locally in the repo of Fraud Detection service.</li><li class="listitem">Add the Spring Cloud Contract Verifier plugin.</li><li class="listitem">Run the integration tests.</li><li class="listitem">File a pull request.</li><li class="listitem">Create an initial implementation.</li><li class="listitem">Take over the pull request.</li><li class="listitem">Write the missing implementation.</li><li class="listitem">Deploy your app.</li><li class="listitem">Work online.</li></ol></div><p><span class="strong"><strong>Start doing TDD by writing a test for your feature.</strong></span></p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> shouldBeRejectedDueToAbnormalLoanAmount() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
LoanApplication application = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoanApplication(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Client(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1234567890"</span>),
|
||||
<span class="hl-number">99999</span>);
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
|
||||
LoanApplicationResult loanApplication = service.loanApplication(application);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
@@ -536,7 +536,7 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/fraudcheck'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (3)</span>
|
||||
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (4)</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"client.id"</span>: $(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{10}'</span>)),
|
||||
loanAmount : <span class="hl-number">99999</span>
|
||||
loanAmount : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
|
||||
])
|
||||
headers { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (5)</span>
|
||||
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
|
||||
@@ -673,18 +673,18 @@ First, add the <code class="literal">Spring Cloud Contract</code> BOM.</p><pre c
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>Since the plugin was added, you get the <code class="literal">Spring Cloud Contract Verifier</code> features which,
|
||||
from the provided contracts:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">generate and run tests</li><li class="listitem">produce and install stubs</li></ul></div><p>You do not want to generate tests since you, as the consumer, want only to play with the
|
||||
stubs. You need to skip the test generation and execution. When you execute:</p><pre class="programlisting">$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> local-http-server-repo
|
||||
$ ./mvnw clean install -DskipTests</pre><p>In the logs, you see something like this:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<span class="hl-number">1.0</span>.<span class="hl-number">0.</span>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
$ ./mvnw clean install -DskipTests</pre><p>In the logs, you see something like this:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
[INFO]
|
||||
[INFO] --- maven-jar-plugin:<span class="hl-number">2.6</span>:jar (default-jar) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.jar
|
||||
[INFO] --- maven-jar-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.6</xslthl:number>:jar (default-jar) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar
|
||||
[INFO]
|
||||
[INFO] --- spring-boot-maven-plugin:<span class="hl-number">1.5</span>.<span class="hl-number">5.</span>BUILD-SNAPSHOT:repackage (default) @ http-server ---
|
||||
[INFO] --- spring-boot-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5.</xslthl:number>BUILD-SNAPSHOT:repackage (default) @ http-server ---
|
||||
[INFO]
|
||||
[INFO] --- maven-install-plugin:<span class="hl-number">2.5</span>.<span class="hl-number">2</span>:install (default-install) @ http-server ---
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.jar
|
||||
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar</pre><p>The following line is extremely important:</p><pre class="programlisting">[INFO] Installing /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar</pre><p>It confirms that the stubs of the <code class="literal">http-server</code> have been installed in the local
|
||||
[INFO] --- maven-install-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>:install (default-install) @ http-server ---
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar
|
||||
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
|
||||
[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar</pre><p>The following line is extremely important:</p><pre class="programlisting">[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar</pre><p>It confirms that the stubs of the <code class="literal">http-server</code> have been installed in the local
|
||||
repository.</p><p><span class="strong"><strong>Run the integration tests.</strong></span></p><p>In order to profit from the Spring Cloud Contract Stub Runner functionality of automatic
|
||||
stub downloading, you must do the following in your consumer side project (<code class="literal">Loan
|
||||
Application service</code>):</p><p>Add the <code class="literal">Spring Cloud Contract</code> BOM:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span>
|
||||
@@ -704,23 +704,23 @@ Application service</code>):</p><p>Add the <code class="literal">Spring Cloud Co
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>Annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation, provide the
|
||||
<code class="literal">group-id</code> and <code class="literal">artifact-id</code> for the Stub Runner to download the stubs of your
|
||||
collaborators. (Optional step) Because you’re playing with the collaborators offline, you
|
||||
can also provide the offline work switch (<code class="literal">StubRunnerProperties.StubsMode.LOCAL</code>).</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureStubRunner(ids = {
|
||||
"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><p>Now, when you run your tests, you see something like this:</p><pre class="programlisting"><span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.403</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.438</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved version is <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.439</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolving artifact com.example:http-server:jar:stubs:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT using remote repositories []
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.451</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved artifact com.example:http-server:jar:stubs:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.465</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar]
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">25.475</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacked file to [/var/folders/<span class="hl-number">0</span>p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
|
||||
<span class="hl-number">2016</span>-<span class="hl-number">07</span>-<span class="hl-number">19</span> <span class="hl-number">14</span>:<span class="hl-number">22</span>:<span class="hl-number">27.737</span> INFO <span class="hl-number">41050</span> --- [ main] o.s.c.c.stubrunner.StubRunnerExecutor : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT:stubs=<span class="hl-number">8080</span>}]</pre><p>This output means that Stub Runner has found your stubs and started a server for your app
|
||||
can also provide the offline work switch (<code class="literal">StubRunnerProperties.StubsMode.LOCAL</code>).</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = {
|
||||
"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><p>Now, when you run your tests, you see something like this:</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.403</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.438</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved version is <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.439</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolving artifact com.example:http-server:jar:stubs:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT using remote repositories []
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.451</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved artifact com.example:http-server:jar:stubs:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.465</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar]
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.475</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacked file to [/var/folders/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">27.737</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.StubRunnerExecutor : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT:stubs=<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8080</xslthl:number>}]</pre><p>This output means that Stub Runner has found your stubs and started a server for your app
|
||||
with group id <code class="literal">com.example</code>, artifact id <code class="literal">http-server</code> with version <code class="literal">0.0.1-SNAPSHOT</code> of
|
||||
the stubs and with <code class="literal">stubs</code> classifier on port <code class="literal">8080</code>.</p><p><span class="strong"><strong>File a pull request.</strong></span></p><p>What you have done until now is an iterative process. You can play around with the
|
||||
contract, install it locally, and work on the consumer side until the contract works as
|
||||
you wish.</p><p>Once you are satisfied with the results and the test passes, publish a pull request to
|
||||
the server side. Currently, the consumer side work is done.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_side_fraud_detection_server" href="#_producer_side_fraud_detection_server"></a>2.5.3 Producer side (Fraud Detection server)</h3></div></div></div><p>As a developer of the Fraud Detection server (a server to the Loan Issuance service):</p><p><span class="strong"><strong>Create an initial implementation.</strong></span></p><p>As a reminder, you can see the initial implementation here:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RequestMapping(value = "/fraudcheck", method = PUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<em><span class="hl-annotation" style="color: gray">@RequestBody</span></em> FraudCheck fraudCheck) {
|
||||
the server side. Currently, the consumer side work is done.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_side_fraud_detection_server" href="#_producer_side_fraud_detection_server"></a>2.5.3 Producer side (Fraud Detection server)</h3></div></div></div><p>As a developer of the Fraud Detection server (a server to the Loan Issuance service):</p><p><span class="strong"><strong>Create an initial implementation.</strong></span></p><p>As a reminder, you can see the initial implementation here:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(value = "/fraudcheck", method = PUT)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestBody</xslthl:annotation> FraudCheck fraudCheck) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
|
||||
}</pre><p><span class="strong"><strong>Take over the pull request.</strong></span></p><pre class="programlisting">$ git checkout -b contract-change-pr master
|
||||
$ git pull https://your-git-server.com/server-side-fork.git contract-change-pr</pre><p>You must add the dependencies needed by the autogenerated tests:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
@@ -766,7 +766,7 @@ start the server side <code class="literal">FraudDetectionController</code>.</p>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FraudBase {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudDetectionController(),
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudStatsController(stubbedStatsProvider()));
|
||||
@@ -776,11 +776,11 @@ start the server side <code class="literal">FraudDetectionController</code>.</p>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> fraudType -> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">switch</span> (fraudType) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">case</span> DRUNKS:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span class="hl-number">100</span>;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">100</xslthl:number>;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">case</span> ALL:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span class="hl-number">200</span>;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>;
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span class="hl-number">0</span>;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -791,9 +791,9 @@ start the server side <code class="literal">FraudDetectionController</code>.</p>
|
||||
}</pre><p>Now, if you run the <code class="literal">./mvnw clean install</code>, you get something like this:</p><pre class="programlisting">Results :
|
||||
|
||||
Tests in error:
|
||||
ContractVerifierTest.validate_shouldMarkClientAsFraud:<span class="hl-number">32</span> » IllegalState Parsed...</pre><p>This error occurs because you have a new contract from which a test was generated and it
|
||||
ContractVerifierTest.validate_shouldMarkClientAsFraud:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">32</xslthl:number> » IllegalState Parsed...</pre><p>This error occurs because you have a new contract from which a test was generated and it
|
||||
failed since you have not implemented the feature. The auto-generated test would look
|
||||
like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
@@ -805,7 +805,7 @@ like this:</p><pre class="programlisting"><em><span class="hl-annotation" style=
|
||||
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1.json.*"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
@@ -818,8 +818,8 @@ in the form of a test. This test sends a request to our own application with the
|
||||
headers, and body defined in the contract. It also is expecting precisely defined values
|
||||
in the response. In other words, you have the <code class="literal">red</code> part of <code class="literal">red</code>, <code class="literal">green</code>, and
|
||||
<code class="literal">refactor</code>. It is time to convert the <code class="literal">red</code> into the <code class="literal">green</code>.</p><p><span class="strong"><strong>Write the missing implementation.</strong></span></p><p>Because you know the expected input and expected output, you can write the missing
|
||||
implementation:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RequestMapping(value = "/fraudcheck", method = PUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<em><span class="hl-annotation" style="color: gray">@RequestBody</span></em> FraudCheck fraudCheck) {
|
||||
implementation:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(value = "/fraudcheck", method = PUT)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestBody</xslthl:annotation> FraudCheck fraudCheck) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (amountGreaterThanThreshold(fraudCheck)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.FRAUD, AMOUNT_TOO_HIGH);
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ work.</p></td></tr></table></div><div class="important" style="margin-left: 0.5i
|
||||
It defines how to send and receive messages. You can create your own implementation to
|
||||
achieve the same goal.</p><p>In a test, you can inject a <code class="literal">ContractVerifierMessageExchange</code> to send and receive
|
||||
messages that follow the contract. Then add <code class="literal">@AutoConfigureMessageVerifier</code> to your test.
|
||||
Here’s an example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringTestRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureMessageVerifier</span></em>
|
||||
Here’s an example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringTestRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureMessageVerifier</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MessagingContractTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MessageVerifier verifier;
|
||||
...
|
||||
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If your tests require stubs as well, then <code class="literal">@AutoConfigureStubRunner</code> includes the
|
||||
|
||||
@@ -153,7 +153,7 @@ endpoint, which should be verified.</p><pre class="programlisting"><span xmlns:d
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> isProperCorrelationId(Integer correlationId) {
|
||||
assert correlationId == <span class="hl-number">123456</span>
|
||||
assert correlationId == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123456</xslthl:number>
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> isEmpty(String value) {
|
||||
@@ -192,20 +192,20 @@ via <code class="literal">contractsProperties</code> method e.g. <code class="li
|
||||
a system property or an environment variable.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-consumer" href="#gradle-consumer"></a>4.1.14 Spring Cloud Contract Verifier on the Consumer Side</h3></div></div></div><p>In a consuming service, you need to configure the Spring Cloud Contract Verifier plugin
|
||||
in exactly the same way as in case of provider. If you do not want to use Stub Runner
|
||||
then you need to copy contracts stored in <code class="literal">src/test/resources/contracts</code> and generate
|
||||
WireMock JSON stubs using:</p><pre class="programlisting">./gradlew generateClientStubs</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">stubsOutputDir</code> option has to be set for stub generation to work.</p></td></tr></table></div><p>When present, JSON stubs can be used in automated tests of consuming a service.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application)</span></em>
|
||||
WireMock JSON stubs using:</p><pre class="programlisting">./gradlew generateClientStubs</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">stubsOutputDir</code> option has to be set for stub generation to work.</p></td></tr></table></div><p>When present, JSON stubs can be used in automated tests of consuming a service.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@ClassRule</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Shared</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Shared</xslthl:annotation>
|
||||
WireMockClassRule wireMockRule == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockClassRule()
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
LoanApplicationService sut
|
||||
|
||||
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should successfully apply for loan'</span>() {
|
||||
given:
|
||||
LoanApplication application =
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoanApplication(client: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Client(clientPesel: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'12345678901'</span>), amount: <span class="hl-number">123.123</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoanApplication(client: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Client(clientPesel: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'12345678901'</span>), amount: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123.123</xslthl:number>)
|
||||
when:
|
||||
LoanApplicationResult loanApplication == sut.loanApplication(application)
|
||||
then:
|
||||
@@ -253,13 +253,13 @@ Assured 2.x by adding it to the plugins classpath, as shown here:</p><pre class=
|
||||
<dependency>
|
||||
<groupId>com.jayway.restassured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version><span class="hl-number">2.5</span>.<span class="hl-number">0</span></version>
|
||||
<version><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number></version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.restassured</groupId>
|
||||
<artifactId>spring-mock-mvc</artifactId>
|
||||
<version><span class="hl-number">2.5</span>.<span class="hl-number">0</span></version>
|
||||
<version><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number></version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -271,13 +271,13 @@ Assured 2.x by adding it to the plugins classpath, as shown here:</p><pre class=
|
||||
<dependency>
|
||||
<groupId>com.jayway.restassured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version><span class="hl-number">2.5</span>.<span class="hl-number">0</span></version>
|
||||
<version><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number></version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.restassured</groupId>
|
||||
<artifactId>spring-mock-mvc</artifactId>
|
||||
<version><span class="hl-number">2.5</span>.<span class="hl-number">0</span></version>
|
||||
<version><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number></version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies></pre><p>That way, the plugin automatically sees that Rest Assured 3.x is present on the classpath
|
||||
@@ -409,14 +409,14 @@ endpoint, which should be verified.</p><pre class="programlisting"><span xmlns:d
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.test.context.junit4.SpringRunner;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BaseTestClass {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
WebApplicationContext context;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssuredMockMvc.webAppContextSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.context);
|
||||
}
|
||||
@@ -430,14 +430,14 @@ similarly, as you might find in regular integration tests.</p><pre class="progra
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.test.context.junit4.SpringRunner;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BaseTestClass {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@LocalServerPort</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LocalServerPort</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssured.baseURI = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span> + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.port;
|
||||
}
|
||||
@@ -544,13 +544,13 @@ goal. Example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>Under <a class="xref" href="multi__using_the_pluggable_architecture.html#scm-stub-downloader" title="10.6 Using the SCM Stub Downloader">Section 10.6, “Using the SCM Stub Downloader”</a> you can find all possible
|
||||
configuration options that you can pass either via
|
||||
the <code class="literal"><configuration><contractProperties></code> map, a system property
|
||||
or an environment variable.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-sts" href="#maven-sts"></a>4.2.12 Maven Plugin and STS</h3></div></div></div><p>If you see the following exception while using STS:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.1.x/docs/src/main/asciidoc/images/sts_exception.png" alt="STS Exception"></div></div><p>When you click on the error marker you should see something like this:</p><pre class="programlisting"> plugin:<span class="hl-number">1.1</span>.<span class="hl-number">0.</span>M1:convert:default-convert:process-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
|
||||
cloud-contract-maven-plugin:<span class="hl-number">1.1</span>.<span class="hl-number">0.</span>M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:<span class="hl-number">145</span>) at
|
||||
org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:<span class="hl-number">331</span>) at org.eclipse.m2e.core.internal.embedder.MavenImpl$<span class="hl-number">11.</span>call(MavenImpl.java:<span class="hl-number">1362</span>) at
|
||||
or an environment variable.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-sts" href="#maven-sts"></a>4.2.12 Maven Plugin and STS</h3></div></div></div><p>If you see the following exception while using STS:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.1.x/docs/src/main/asciidoc/images/sts_exception.png" alt="STS Exception"></div></div><p>When you click on the error marker you should see something like this:</p><pre class="programlisting"> plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.1</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>M1:convert:default-convert:process-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
|
||||
cloud-contract-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.1</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">145</xslthl:number>) at
|
||||
org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">331</xslthl:number>) at org.eclipse.m2e.core.internal.embedder.MavenImpl$<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">11.</xslthl:number>call(MavenImpl.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1362</xslthl:number>) at
|
||||
...
|
||||
org.eclipse.core.internal.jobs.Worker.run(Worker.java:<span class="hl-number">55</span>) Caused by: java.lang.NullPointerException at
|
||||
org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseIncrementalBuildContext.hasDelta(EclipseIncrementalBuildContext.java:<span class="hl-number">53</span>) at
|
||||
org.sonatype.plexus.build.incremental.ThreadBuildContext.hasDelta(ThreadBuildContext.java:<span class="hl-number">59</span>) at</pre><p>In order to fix this issue, provide the following section in your <code class="literal">pom.xml</code>:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><build></span>
|
||||
org.eclipse.core.internal.jobs.Worker.run(Worker.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">55</xslthl:number>) Caused by: java.lang.NullPointerException at
|
||||
org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseIncrementalBuildContext.hasDelta(EclipseIncrementalBuildContext.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">53</xslthl:number>) at
|
||||
org.sonatype.plexus.build.incremental.ThreadBuildContext.hasDelta(ThreadBuildContext.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">59</xslthl:number>) at</pre><p>In order to fix this issue, provide the following section in your <code class="literal">pom.xml</code>:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><build></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pluginManagement></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugins></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!--This plugin's configuration is used to store Eclipse m2e settings
|
||||
@@ -590,13 +590,13 @@ Please refer to the example below:</p><pre class="programlisting"></pre><p>If yo
|
||||
Surefire plugin setup, like in the following example:</p><pre class="programlisting"></pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stubs_and_transitive_dependencies" href="#_stubs_and_transitive_dependencies"></a>4.3 Stubs and Transitive Dependencies</h2></div></div></div><p>The Maven and Gradle plugin that add the tasks that create the stubs jar for you. One
|
||||
problem that arises is that, when reusing the stubs, you can mistakenly import all of
|
||||
that stub’s dependencies. When building a Maven artifact, even though you have a couple
|
||||
of different jars, all of them share one pom:</p><pre class="programlisting">├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-<span class="hl-number">20160903.075506</span>-<span class="hl-number">1</span>-stubs.jar
|
||||
├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-<span class="hl-number">20160903.075506</span>-<span class="hl-number">1</span>-stubs.jar.sha1
|
||||
├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-<span class="hl-number">20160903.075655</span>-<span class="hl-number">2</span>-stubs.jar
|
||||
├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-<span class="hl-number">20160903.075655</span>-<span class="hl-number">2</span>-stubs.jar.sha1
|
||||
├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-SNAPSHOT.jar
|
||||
├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-SNAPSHOT.pom
|
||||
├── github-webhook-<span class="hl-number">0.0</span>.<span class="hl-number">1.</span>BUILD-SNAPSHOT-stubs.jar
|
||||
of different jars, all of them share one pom:</p><pre class="programlisting">├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075506</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-stubs.jar
|
||||
├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075506</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-stubs.jar.sha1
|
||||
├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075655</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>-stubs.jar
|
||||
├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075655</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>-stubs.jar.sha1
|
||||
├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-SNAPSHOT.jar
|
||||
├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-SNAPSHOT.pom
|
||||
├── github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-SNAPSHOT-stubs.jar
|
||||
├── ...
|
||||
└── ...</pre><p>There are three possibilities of working with those dependencies so as not to have any
|
||||
issues with transitive dependencies:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Mark all application dependencies as optional</li><li class="listitem">Create a separate artifactid for the stubs</li><li class="listitem">Exclude dependencies on the consumer side</li></ul></div><p><span class="strong"><strong>Mark all application dependencies as optional</strong></span></p><p>If, in the <code class="literal">github-webhook</code> application, you mark all of your dependencies as optional,
|
||||
|
||||
@@ -8,23 +8,23 @@ the default with <code class="literal">spring-boot-starter-web</code>), you can
|
||||
<code class="literal">spring-cloud-starter-contract-stub-runner</code> to your classpath and add <code class="literal">@AutoConfigureWireMock</code> in
|
||||
order to be able to use Wiremock in your tests. Wiremock runs as a stub server and you
|
||||
can register stub behavior using a Java API or via static JSON declarations as part of
|
||||
your test. The following code shows an example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureWireMock(port = 0)</span></em>
|
||||
your test. The following code shows an example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureWireMock(port = 0)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockForDocsTests {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// A service that calls out over HTTP</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Service service;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.service.setBase(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span>
|
||||
+ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"wiremock.server.port"</span>));
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Using the WireMock APIs in the normal way:</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Stubbing WireMock</span>
|
||||
stubFor(get(urlEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>)).willReturn(aResponse()
|
||||
@@ -58,7 +58,7 @@ public class WiremockImportApplicationTests {
|
||||
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Actually, WireMock always loads mappings from <code class="literal">src/test/resources/mappings</code> <span class="strong"><strong>as
|
||||
well as</strong></span> the custom locations in the stubs attribute. To change this behavior, you can
|
||||
also specify a files root as described in the next section of this document.</p></td></tr></table></div><p>If you’re using Spring Cloud Contract’s default stub jars, then your
|
||||
stubs are stored under <code class="literal">/META-INF/group-id/artifact-id/versions/mappings/</code> folder. If you want to register all stubs from that location, from all embedded JARs, then it’s enough to use the following syntax.</p><pre class="programlisting">@AutoConfigureWireMock(port = <span class="hl-number">0</span>, stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath*:/META-INF/**/mappings/**/*.json"</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_files_to_specify_the_stub_bodies" href="#_using_files_to_specify_the_stub_bodies"></a>11.2 Using Files to Specify the Stub Bodies</h2></div></div></div><p>WireMock can read response bodies from files on the classpath or the file system. In that
|
||||
stubs are stored under <code class="literal">/META-INF/group-id/artifact-id/versions/mappings/</code> folder. If you want to register all stubs from that location, from all embedded JARs, then it’s enough to use the following syntax.</p><pre class="programlisting">@AutoConfigureWireMock(port = <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>, stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath*:/META-INF/**/mappings/**/*.json"</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_files_to_specify_the_stub_bodies" href="#_using_files_to_specify_the_stub_bodies"></a>11.2 Using Files to Specify the Stub Bodies</h2></div></div></div><p>WireMock can read response bodies from files on the classpath or the file system. In that
|
||||
case, you can see in the JSON DSL that the response has a <code class="literal">bodyFileName</code> instead of a
|
||||
(literal) <code class="literal">body</code>. The files are resolved relative to a root directory (by default,
|
||||
<code class="literal">src/test/resources/__files</code>). To customize this location you can set the <code class="literal">files</code>
|
||||
@@ -71,27 +71,27 @@ automatic loading of stubs, because they come from the root location
|
||||
in a subdirectory called "mappings". The value of <code class="literal">files</code> has no
|
||||
effect on the stubs loaded explicitly from the <code class="literal">stubs</code> attribute.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_alternative_using_junit_rules" href="#_alternative_using_junit_rules"></a>11.3 Alternative: Using JUnit Rules</h2></div></div></div><p>For a more conventional WireMock experience, you can use JUnit <code class="literal">@Rules</code> to start and stop
|
||||
the server. To do so, use the <code class="literal">WireMockSpring</code> convenience class to obtain an <code class="literal">Options</code>
|
||||
instance, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)</span></em>
|
||||
instance, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockForDocsClassRuleTests {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start WireMock on some dynamic port</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// for some reason `dynamicPort()` is not working properly</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@ClassRule</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> WireMockClassRule wiremock = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockClassRule(
|
||||
WireMockSpring.options().dynamicPort());
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// A service that calls out over HTTP to wiremock's port</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Service service;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.service.setBase(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span> + wiremock.port());
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Using the WireMock APIs in the normal way:</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Stubbing WireMock</span>
|
||||
wiremock.stubFor(get(urlEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>)).willReturn(aResponse()
|
||||
@@ -107,21 +107,21 @@ the SSL certificates are not valid (the usual problem with self-installed certif
|
||||
The best option is often to re-configure the client to use "http". If that’s not an
|
||||
option, you can ask Spring to configure an HTTP client that ignores SSL validation errors
|
||||
(do so only for tests, of course).</p><p>To make this work with minimum fuss, you need to be using the Spring Boot
|
||||
<code class="literal">RestTemplateBuilder</code> in your app, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<code class="literal">RestTemplateBuilder</code> in your app, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> builder.build();
|
||||
}</pre><p>You need <code class="literal">RestTemplateBuilder</code> because the builder is passed through callbacks to
|
||||
initialize it, so the SSL validation can be set up in the client at that point. This
|
||||
happens automatically in your test if you are using the <code class="literal">@AutoConfigureWireMock</code>
|
||||
annotation or the stub runner. If you use the JUnit <code class="literal">@Rule</code> approach, you need to add the
|
||||
<code class="literal">@AutoConfigureHttpClient</code> annotation as well, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest("app.baseUrl=https://localhost:6443")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureHttpClient</span></em>
|
||||
<code class="literal">@AutoConfigureHttpClient</code> annotation as well, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest("app.baseUrl=https://localhost:6443")</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureHttpClient</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockHttpsServerApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@ClassRule</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> WireMockClassRule wiremock = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockClassRule(
|
||||
WireMockSpring.options().httpsPort(<span class="hl-number">6443</span>));
|
||||
WireMockSpring.options().httpsPort(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">6443</xslthl:number>));
|
||||
...
|
||||
}</pre><p>If you are using <code class="literal">spring-boot-starter-test</code>, you have the Apache HTTP client on the
|
||||
classpath and it is selected by the <code class="literal">RestTemplateBuilder</code> and configured to ignore SSL
|
||||
@@ -129,17 +129,17 @@ errors. If you use the default <code class="literal">java.net</code> client, you
|
||||
won’t do any harm). There is no support currently for other clients, but it may be added
|
||||
in future releases.</p><p>To disable the custom <code class="literal">RestTemplateBuilder</code>, set the <code class="literal">wiremock.rest-template-ssl-enabled</code>
|
||||
property to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_wiremock_and_spring_mvc_mocks" href="#_wiremock_and_spring_mvc_mocks"></a>11.5 WireMock and Spring MVC Mocks</h2></div></div></div><p>Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into
|
||||
a Spring <code class="literal">MockRestServiceServer</code>. The following code shows an example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</span></em>
|
||||
a Spring <code class="literal">MockRestServiceServer</code>. The following code shows an example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockForDocsMockServerApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> RestTemplate restTemplate;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Service service;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// will read stubs classpath</span>
|
||||
MockRestServiceServer server = WireMockRestServiceServer.with(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.restTemplate)
|
||||
@@ -162,10 +162,10 @@ Spring Boot embedded servers, and Wiremock itself has "native" support for a par
|
||||
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).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customization_of_wiremock_configuration" href="#_customization_of_wiremock_configuration"></a>11.6 Customization of WireMock configuration</h2></div></div></div><p>You can register a bean of <code class="literal">org.springframework.cloud.contract.wiremock.WireMockConfigurationCustomizer</code> type
|
||||
in order to customize the WireMock configuration (e.g. add custom transformers).
|
||||
Example:</p><pre class="programlisting"> <em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
Example:</p><pre class="programlisting"> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
WireMockConfigurationCustomizer optionsCustomizer() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockConfigurationCustomizer() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> customize(WireMockConfiguration options) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// perform your customization here</span>
|
||||
}
|
||||
@@ -176,16 +176,16 @@ or <code class="literal">WebTestClient</code> or Rest Assured. At the same time
|
||||
generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your
|
||||
normal REST Docs test cases and use <code class="literal">@AutoConfigureRestDocs</code> to have stubs be
|
||||
automatically generated in the REST Docs output directory. The following code shows an
|
||||
example using <code class="literal">MockMvc</code>:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureRestDocs(outputDir = "target/snippets")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureMockMvc</span></em>
|
||||
example using <code class="literal">MockMvc</code>:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureRestDocs(outputDir = "target/snippets")</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureMockMvc</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MockMvc mockMvc;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
mockMvc.perform(get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>))
|
||||
.andExpect(content().string(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span>))
|
||||
@@ -193,16 +193,16 @@ example using <code class="literal">MockMvc</code>:</p><pre class="programlistin
|
||||
}
|
||||
}</pre><p>This test generates a WireMock stub at "target/snippets/stubs/resource.json". It matches
|
||||
all GET requests to the "/resource" path. The same example with <code class="literal">WebTestClient</code> (used
|
||||
for testing Spring WebFlux applications) would look like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureRestDocs(outputDir = "target/snippets")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureWebTestClient</span></em>
|
||||
for testing Spring WebFlux applications) would look like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureRestDocs(outputDir = "target/snippets")</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureWebTestClient</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> WebTestClient client;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
client.get().uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>).exchange()
|
||||
.expectBody(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span>)
|
||||
@@ -236,7 +236,7 @@ matchers. If JSON Path is unfamiliar, The <a class="link" href="https://github.c
|
||||
documentation</a> can help you get up to speed. The <code class="literal">WebTestClient</code> version of this test
|
||||
has a similar <code class="literal">verify()</code> static helper that you insert in the same place.</p><p>Instead of the <code class="literal">jsonPath</code> and <code class="literal">contentType</code> convenience methods, you can also use the
|
||||
WireMock APIs to verify that the request matches the created stub, as shown in the
|
||||
following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
mockMvc.perform(post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>)
|
||||
.content(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"id\":\"123456\",\"message\":\"Hello World\"}"</span>))
|
||||
@@ -258,7 +258,7 @@ range of parameters. The above example generates a stub resembling the following
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"X-Application-Context"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application:-1"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
@@ -299,7 +299,7 @@ Contract.make {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'POST'</span>
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/foo'</span>
|
||||
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span> {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>: <span class="hl-number">23</span> }
|
||||
</span> {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">23</xslthl:number> }
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">')
|
||||
</span> headers {
|
||||
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Accept'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
|
||||
|
||||
@@ -8,7 +8,7 @@ can generate tests for other languages) and the way stubs are generated (for exa
|
||||
can generate stubs for other HTTP server implementations).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_contract_converter" href="#_custom_contract_converter"></a>10.1 Custom Contract Converter</h2></div></div></div><p>The <code class="literal">ContractConverter</code> interface lets you register your own implementation of a contract
|
||||
structure converter. The following code listing shows the <code class="literal">ContractConverter</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.spec
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Converter to be used to convert FROM {@link File} TO {@link Contract}
|
||||
* and from {@link Contract} to {@code T}
|
||||
*
|
||||
@@ -16,32 +16,32 @@ structure converter. The following code listing shows the <code class="literal">
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> ContractConverter<T> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> ContractStorer<T> {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Should this file be accepted by the converter. Can use the file extension
|
||||
* to check if the conversion is possible.
|
||||
*
|
||||
* @param file - file to be considered for conversion
|
||||
* @return - {@code true} if the given implementation can convert the file
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isAccepted(File file)
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Converts the given {@link File} to its {@link Contract} representation
|
||||
*
|
||||
* @param file - file to convert
|
||||
* @return - {@link Contract} representation of the file
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
Collection<Contract> convertFrom(File file)
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Converts the given {@link Contract} to a {@link T} representation
|
||||
*
|
||||
* @param contract - the parsed contract
|
||||
* @return - {@link T} the type to which we do the conversion
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
T convertTo(Collection<Contract> contract)
|
||||
}</pre><p>Your implementation must define the condition on which it should start the
|
||||
conversion. Also, you must define how to perform that conversion in both directions.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Once you create your implementation, you must create a
|
||||
@@ -76,7 +76,7 @@ set a <code class="literal">metaData</code> entry in the Pact file, with key <co
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span>: {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clientId"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1234567890"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanAmount"</span>: <span class="hl-number">99999</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanAmount"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"generators"</span>: {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span>: {
|
||||
@@ -112,7 +112,7 @@ set a <code class="literal">metaData</code> entry in the Pact file, with key <co
|
||||
}
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span>: {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span class="hl-number">200</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span>: {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json;charset=UTF-8"</span>
|
||||
},
|
||||
@@ -177,7 +177,7 @@ the current Pact version that you use.</p><p class="primary"><b>Maven. </b>
|
||||
</p><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-contract-pact:${findProperty('verifierVersion') ?: verifierVersion}"</span></pre><p class="secondary">
|
||||
</p><p>When you execute the build of your application, a test will be generated. The generated
|
||||
test might be as follows:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
test might be as follows:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
@@ -189,7 +189,7 @@ test might be as follows:</p><pre class="programlisting"><em><span class="hl-ann
|
||||
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd\\.fraud\\.v1\\+json.*"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
@@ -214,7 +214,7 @@ test might be as follows:</p><pre class="programlisting"><em><span class="hl-ann
|
||||
} ]
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json;charset=UTF-8"</span>
|
||||
@@ -239,14 +239,14 @@ following code listing shows the <code class="literal">SingleTestGenerator</code
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Builds a single test.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
trait SingleTestGenerator {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Creates contents of a single test class in which all test scenarios from
|
||||
* the contract metadata should be placed.
|
||||
*
|
||||
@@ -257,12 +257,12 @@ trait SingleTestGenerator {
|
||||
* @param includedDirectoryRelativePath - relative path to the included directory
|
||||
* @return contents of a single test class
|
||||
* @deprecated use{@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
|
||||
*/</strong>
|
||||
<em><span class="hl-annotation" style="color: gray">@Deprecated</span></em>
|
||||
*/</xslthl:doccomment>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Deprecated</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> String buildClass(ContractVerifierConfigProperties properties,
|
||||
Collection<ContractMetadata> listOfFiles, String className, String classPackage, String includedDirectoryRelativePath)
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Creates contents of a single test class in which all test scenarios from
|
||||
* the contract metadata should be placed.
|
||||
*
|
||||
@@ -271,7 +271,7 @@ trait SingleTestGenerator {
|
||||
* @param generatedClassData - information about the generated class
|
||||
* @param includedDirectoryRelativePath - relative path to the included directory
|
||||
* @return contents of a single test class
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
String buildClass(ContractVerifierConfigProperties properties,
|
||||
Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
|
||||
String className = generatedClassData.className
|
||||
@@ -280,11 +280,11 @@ trait SingleTestGenerator {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> buildClass(properties, listOfFiles, className, classPackage, path)
|
||||
}
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Extension that should be appended to the generated test class. E.g. {@code .java} or {@code .php}
|
||||
*
|
||||
* @param properties - properties passed to the plugin
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> String fileExtension(ContractVerifierConfigProperties properties)
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> GeneratedClassData {
|
||||
@@ -310,26 +310,26 @@ own implementation of the <code class="literal">StubGenerator</code> interface.
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Converts contracts into their stub representation.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/</strong>
|
||||
<em><span class="hl-annotation" style="color: gray">@CompileStatic</span></em>
|
||||
*/</xslthl:doccomment>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@CompileStatic</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StubGenerator {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* @return {@code true} if the converter can handle the file to convert it into a stub.
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> canHandleFileName(String fileName)
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* @return the collection of converted contracts into stubs. One contract can
|
||||
* result in multiple stubs.
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
Map<Contract, String> convertContents(String rootName, ContractMetadata content)
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* @return the name of the converted stub file. If you have multiple contracts
|
||||
* in a single file then a prefix will be added to the generated file. If you
|
||||
* provide the {@link Contract#name} field then that field will override the
|
||||
@@ -338,7 +338,7 @@ own implementation of the <code class="literal">StubGenerator</code> interface.
|
||||
* Example: name of file with 2 contracts is {@code foo.groovy}, it will be
|
||||
* converted by the implementation to {@code foo.json}. The recursive file
|
||||
* converter will create two files {@code 0_foo.json} and {@code 1_foo.json}
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
String generateOutputFileNameForInput(String inputFileName)
|
||||
}</pre><p>Again, you must provide a <code class="literal">spring.factories</code> file, such as the one shown in the following
|
||||
example:</p><pre class="screen"># Stub converters
|
||||
@@ -357,38 +357,38 @@ HTTP Stub server implementation, which might resemble the following example:</p>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.stubrunner.HttpServerStub
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.util.SocketUtils
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Commons</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Commons</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MocoHttpServerStub <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HttpServerStub {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> started
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> JsonRunner runner
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (!isRunning()) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> -<span class="hl-number">1</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> -<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> port
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isRunning() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> started
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
HttpServerStub start() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> start(SocketUtils.findAvailableTcpPort())
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
HttpServerStub start(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.port = port
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
HttpServerStub stop() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (!isRunning()) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
|
||||
@@ -397,7 +397,7 @@ HTTP Stub server implementation, which might resemble the following example:</p>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
HttpServerStub registerMappings(Collection<File> stubFiles) {
|
||||
List<RunnerSetting> settings = stubFiles.findAll { it.name.endsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"json"</span>) }
|
||||
.collect {
|
||||
@@ -418,12 +418,12 @@ HTTP Stub server implementation, which might resemble the following example:</p>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
String registeredMappings() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isAccepted(File file) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> file.name.endsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">".json"</span>)
|
||||
}
|
||||
@@ -435,10 +435,10 @@ implementation is used. If you provide more than one, the first one on the list
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomStubDownloaderBuilder <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> StubDownloaderBuilder {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> StubDownloader build(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> StubRunnerOptions stubRunnerOptions) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubDownloader() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Map.Entry<StubConfiguration, File> downloadAndUnpackStubJar(
|
||||
StubConfiguration config) {
|
||||
File unpackedStubs = retrieveStubs();
|
||||
|
||||
@@ -215,7 +215,7 @@ Contract.make {
|
||||
body(fileAsBytes(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request.pdf"</span>))
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
body(fileAsBytes(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response.pdf"</span>))
|
||||
headers {
|
||||
contentType(applicationOctetStream())
|
||||
@@ -251,13 +251,13 @@ response:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// with following response after receiving request</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// specified in "request" part above).</span>
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Contract priority, which can be used for overriding</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// contracts (1 is highest). Priority is optional.</span>
|
||||
priority <span class="hl-number">1</span>
|
||||
priority <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">priority: 8
|
||||
@@ -280,7 +280,7 @@ same information is mandatory in request definition of the Contract.</p><p><b>Gr
|
||||
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -298,7 +298,7 @@ the recommended way, as doing so makes the tests <span class="strong"><strong>ho
|
||||
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -321,7 +321,7 @@ the recommended way, as doing so makes the tests <span class="strong"><strong>ho
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// If a simple literal is used as value</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// default matcher function is used (equalTo)</span>
|
||||
parameter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'limit'</span>: <span class="hl-number">100</span>
|
||||
parameter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'limit'</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">100</xslthl:number>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `equalTo` function simply compares passed value</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// using identity operator (==).</span>
|
||||
@@ -333,11 +333,11 @@ the recommended way, as doing so makes the tests <span class="strong"><strong>ho
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `matching` function tests parameter</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// against passed regular expression.</span>
|
||||
parameter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'offset'</span>: value(consumer(matching(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]+"</span>)), producer(<span class="hl-number">123</span>))
|
||||
parameter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'offset'</span>: value(consumer(matching(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]+"</span>)), producer(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number>))
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `notMatching` functions tests if parameter</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// does not match passed regular expression.</span>
|
||||
parameter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loginStartsWith'</span>: value(consumer(notMatching(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">".{0,2}"</span>)), producer(<span class="hl-number">3</span>))
|
||||
parameter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loginStartsWith'</span>: value(consumer(notMatching(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">".{0,2}"</span>)), producer(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ the recommended way, as doing so makes the tests <span class="strong"><strong>ho
|
||||
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -422,7 +422,7 @@ response:
|
||||
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -450,7 +450,7 @@ headers:
|
||||
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -473,7 +473,7 @@ cookies:
|
||||
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -537,7 +537,7 @@ parametrization of either <code class="literal">fileName</code> or <code class="
|
||||
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/multipart"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);</pre><p>The WireMock stub is as follows:</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);</pre><p>The WireMock stub is as follows:</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/multipart"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
@@ -556,7 +556,7 @@ parametrization of either <code class="literal">fileName</code> or <code class="
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"transformers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response-template"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo-transformer"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
@@ -603,7 +603,7 @@ for requests that follow a given pattern. Also, you can use regular expressions
|
||||
need to use patterns and not exact values both for your test and your server side tests.</p><p>The following example shows how to use regular expressions to write a request:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>)
|
||||
url $(consumer(~/\/[<span class="hl-number">0</span>-<span class="hl-number">9</span>]{<span class="hl-number">2</span>}/), producer(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/12'</span>))
|
||||
url $(consumer(~/\/[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>]{<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>}/), producer(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/12'</span>))
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
@@ -674,7 +674,7 @@ use in your contracts, as shown in the following example:</p><pre class="program
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern NON_EMPTY = Pattern.compile(/[\S\s]+/)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern NON_BLANK = Pattern.compile(/^\s*\S[\S\s]*/)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern ISO8601_WITH_OFFSET = Pattern.
|
||||
compile(/([<span class="hl-number">0</span>-<span class="hl-number">9</span>]{<span class="hl-number">4</span>})-(<span class="hl-number">1</span>[<span class="hl-number">0</span>-<span class="hl-number">2</span>]|<span class="hl-number">0</span>[<span class="hl-number">1</span>-<span class="hl-number">9</span>])-(<span class="hl-number">3</span>[<span class="hl-number">01</span>]|<span class="hl-number">0</span>[<span class="hl-number">1</span>-<span class="hl-number">9</span>]|[<span class="hl-number">12</span>][<span class="hl-number">0</span>-<span class="hl-number">9</span>])T(<span class="hl-number">2</span>[<span class="hl-number">0</span>-<span class="hl-number">3</span>]|[<span class="hl-number">01</span>][<span class="hl-number">0</span>-<span class="hl-number">9</span>]):([<span class="hl-number">0</span>-<span class="hl-number">5</span>][<span class="hl-number">0</span>-<span class="hl-number">9</span>]):([<span class="hl-number">0</span>-<span class="hl-number">5</span>][<span class="hl-number">0</span>-<span class="hl-number">9</span>])(\.\d{<span class="hl-number">3</span>})?(Z|[+-][<span class="hl-number">01</span>]\d:[<span class="hl-number">0</span>-<span class="hl-number">5</span>]\d)/)
|
||||
compile(/([<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>]{<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>})-(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>]|<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>])-(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>]|<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>]|[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">12</xslthl:number>][<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>])T(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>]|[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>][<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>]):([<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number>][<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>]):([<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number>][<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>])(\.\d{<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>})?(Z|[+-][<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>]\d:[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number>]\d)/)
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> Pattern anyOf(String... values) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(values.collect({ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"^$it\$"</span> }).join(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"|"</span>))
|
||||
@@ -755,7 +755,7 @@ RegexProperty nonEmpty() {
|
||||
RegexProperty nonBlank() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(NON_BLANK).asString()
|
||||
}</pre><p>In your contract, you can use it as shown in the following example:</p><pre class="programlisting">Contract dslWithOptionalsInString = Contract.make {
|
||||
priority <span class="hl-number">1</span>
|
||||
priority <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>
|
||||
request {
|
||||
method POST()
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/users/password'</span>
|
||||
@@ -768,7 +768,7 @@ RegexProperty nonBlank() {
|
||||
)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">404</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
@@ -850,7 +850,7 @@ T anyOf(String... values)</pre><p>and this is an example of how you can referenc
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_passing_optional_parameters" href="#_passing_optional_parameters"></a>8.5.3 Passing Optional Parameters</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL. Check out the
|
||||
<a class="xref" href="multi_contract-dsl.html#contract-matchers" title="8.5.7 Dynamic Properties in the Matchers Sections">Section 8.5.7, “Dynamic Properties in the Matchers Sections”</a> section for YAML examples of a similar feature.</p></td></tr></table></div><p>It is possible to provide optional parameters in your contract. However, you can provide
|
||||
optional parameters only for the following:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="emphasis"><em>STUB</em></span> side of the Request</li><li class="listitem"><span class="emphasis"><em>TEST</em></span> side of the Response</li></ul></div><p>The following example shows how to provide optional parameters:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
priority <span class="hl-number">1</span>
|
||||
priority <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>
|
||||
request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'POST'</span>
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/users/password'</span>
|
||||
@@ -863,7 +863,7 @@ optional parameters only for the following:</p><div class="itemizedlist"><ul cla
|
||||
)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">404</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>
|
||||
headers {
|
||||
header <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Content-Type'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>
|
||||
}
|
||||
@@ -883,7 +883,7 @@ expression that must be present 0 or more times.</p><p>If you use Spock for, the
|
||||
.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/users/password"</span>)
|
||||
|
||||
then:
|
||||
response.statusCode == <span class="hl-number">404</span>
|
||||
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>
|
||||
response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Content-Type'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>
|
||||
and:
|
||||
DocumentContext parsedJson = JsonPath.parse(response.body.asString())
|
||||
@@ -905,13 +905,13 @@ expression that must be present 0 or more times.</p><p>If you use Spock for, the
|
||||
}
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">404</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>code\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">123123</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>message\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>User not found by email == [not.existing<em><span class="hl-annotation" style="color: gray">@user.com]\\"}",</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>code\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123123</xslthl:number>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>message\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>User not found by email == [not.existing<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@user.com]\\"}",</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
}
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"priority"</span> : <span class="hl-number">1</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"priority"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_executing_custom_methods_on_the_server_side" href="#_executing_custom_methods_on_the_server_side"></a>8.5.4 Executing Custom Methods on the Server Side</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL. Check out the
|
||||
<a class="xref" href="multi_contract-dsl.html#contract-matchers" title="8.5.7 Dynamic Properties in the Matchers Sections">Section 8.5.7, “Dynamic Properties in the Matchers Sections”</a> section for YAML examples of a similar feature.</p></td></tr></table></div><p>You can define a method call that executes on the server side during the test. Such a
|
||||
@@ -943,7 +943,7 @@ following code shows an example of the contract portion of the test case:</p><pr
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> isProperCorrelationId(Integer correlationId) {
|
||||
assert correlationId == <span class="hl-number">123456</span>
|
||||
assert correlationId == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123456</xslthl:number>
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> isEmpty(String value) {
|
||||
@@ -977,7 +977,7 @@ It should resemble the following code:</p><pre class="programlisting"><span xmln
|
||||
.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/something"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_referencing_the_request_from_the_response" href="#_referencing_the_request_from_the_response"></a>8.5.5 Referencing the Request from the Response</h3></div></div></div><p>The best situation is to provide fixed values, but sometimes you need to reference a
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_referencing_the_request_from_the_response" href="#_referencing_the_request_from_the_response"></a>8.5.5 Referencing the Request from the Response</h3></div></div></div><p>The best situation is to provide fixed values, but sometimes you need to reference a
|
||||
request in your response.</p><p>If you’re writing contracts using Groovy DSL, you can use the <code class="literal">fromRequest()</code> method, which lets
|
||||
you reference a bunch of elements from the HTTP request. You can use the following
|
||||
options:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">fromRequest().url()</code>: Returns the request URL and query parameters.</li><li class="listitem"><code class="literal">fromRequest().query(String key)</code>: Returns the first query parameter with a given name.</li><li class="listitem"><code class="literal">fromRequest().query(String key, int index)</code>: Returns the nth query parameter with a
|
||||
@@ -1033,7 +1033,7 @@ response:
|
||||
.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/api/v1/xxxx"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Authorization"</span>)).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo secret bar"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
@@ -1044,7 +1044,7 @@ response:
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['param']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['paramIndex']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar2"</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['pathIndex']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"v1"</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['responseBaz']"</span>).isEqualTo(<span class="hl-number">5</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['responseBaz']"</span>).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['responseFoo']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['url']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/api/v1/xxxx?foo=bar&foo=bar2"</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['responseBaz2']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Bla bla bar bla bla"</span>);</pre><p>As you can see, elements from the request have been properly referenced in the response.</p><p>The generated WireMock stub should resemble the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
@@ -1068,7 +1068,7 @@ response:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"authorization\":\"{{{request.headers.Authorization.[0]}}}\",\"path\":\"{{{request.path}}}\",\"responseBaz\":{{{jsonpath this '$.baz'}}} ,\"param\":\"{{{request.query.foo.[0]}}}\",\"pathIndex\":\"{{{request.path.[1]}}}\",\"responseBaz2\":\"Bla bla {{{jsonpath this '$.foo'}}} bla bla\",\"responseFoo\":\"{{{jsonpath this '$.foo'}}}\",\"authorization2\":\"{{{request.headers.Authorization.[1]}}}\",\"fullBody\":\"{{{escapejsonbody}}}\",\"url\":\"{{{request.url}}}\",\"paramIndex\":\"{{{request.query.foo.[1]}}}\"}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Authorization"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{{{request.headers.Authorization.[0]}}};foo"</span>
|
||||
@@ -1086,7 +1086,7 @@ in sending the following response body:</p><pre class="programlisting"><span xml
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"authorization2"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secret2"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fullBody"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"foo\":\"bar\",\"baz\":5}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"responseFoo"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"responseBaz"</span> : <span class="hl-number">5</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"responseBaz"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"responseBaz2"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Bla bla bar bla bla"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This feature works only with WireMock having a version greater than or equal
|
||||
to 2.5.1. The Spring Cloud Contract Verifier uses WireMock’s
|
||||
@@ -1120,11 +1120,11 @@ org.springframework.cloud.contract.stubrunner.TestCustomYamlContractConverter</p
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.github.tomakehurst.wiremock.extension.Extension
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Extension that registers the default transformer and the custom one
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> TestWireMockExtensions <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> WireMockExtensions {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
List<Extension> extensions() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> [
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> DefaultResponseTransformer(),
|
||||
@@ -1135,7 +1135,7 @@ org.springframework.cloud.contract.stubrunner.TestCustomYamlContractConverter</p
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomExtension <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> Extension {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
String getName() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo-transformer"</span>
|
||||
}
|
||||
@@ -1179,9 +1179,9 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
|
||||
urlPath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/get'</span>
|
||||
body([
|
||||
duck : <span class="hl-number">123</span>,
|
||||
duck : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number>,
|
||||
alpha : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'abc'</span>,
|
||||
number : <span class="hl-number">123</span>,
|
||||
number : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number>,
|
||||
aBoolean : true,
|
||||
date : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'2017-01-01'</span>,
|
||||
dateTime : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'2017-01-01T01:23:45'</span>,
|
||||
@@ -1211,13 +1211,13 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
|
||||
response {
|
||||
status OK()
|
||||
body([
|
||||
duck : <span class="hl-number">123</span>,
|
||||
duck : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number>,
|
||||
alpha : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'abc'</span>,
|
||||
number : <span class="hl-number">123</span>,
|
||||
positiveInteger : <span class="hl-number">1234567890</span>,
|
||||
negativeInteger : -<span class="hl-number">1234567890</span>,
|
||||
positiveDecimalNumber: <span class="hl-number">123.4567890</span>,
|
||||
negativeDecimalNumber: -<span class="hl-number">123.4567890</span>,
|
||||
number : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number>,
|
||||
positiveInteger : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1234567890</xslthl:number>,
|
||||
negativeInteger : -<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1234567890</xslthl:number>,
|
||||
positiveDecimalNumber: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123.4567890</xslthl:number>,
|
||||
negativeDecimalNumber: -<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123.4567890</xslthl:number>,
|
||||
aBoolean : true,
|
||||
date : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'2017-01-01'</span>,
|
||||
dateTime : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'2017-01-01T01:23:45'</span>,
|
||||
@@ -1225,13 +1225,13 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
|
||||
valueWithoutAMatcher : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>,
|
||||
valueWithTypeMatch : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'string'</span>,
|
||||
valueWithMin : [
|
||||
<span class="hl-number">1</span>, <span class="hl-number">2</span>, <span class="hl-number">3</span>
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>
|
||||
],
|
||||
valueWithMax : [
|
||||
<span class="hl-number">1</span>, <span class="hl-number">2</span>, <span class="hl-number">3</span>
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>
|
||||
],
|
||||
valueWithMinMax : [
|
||||
<span class="hl-number">1</span>, <span class="hl-number">2</span>, <span class="hl-number">3</span>
|
||||
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>
|
||||
],
|
||||
valueWithMinEmpty : [],
|
||||
valueWithMaxEmpty : [],
|
||||
@@ -1262,24 +1262,24 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.valueWithTypeMatch'</span>, byType())
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.valueWithMin'</span>, byType {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// results in verification of size of array (min 1)</span>
|
||||
minOccurrence(<span class="hl-number">1</span>)
|
||||
minOccurrence(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>)
|
||||
})
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.valueWithMax'</span>, byType {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// results in verification of size of array (max 3)</span>
|
||||
maxOccurrence(<span class="hl-number">3</span>)
|
||||
maxOccurrence(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>)
|
||||
})
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.valueWithMinMax'</span>, byType {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// results in verification of size of array (min 1 & max 3)</span>
|
||||
minOccurrence(<span class="hl-number">1</span>)
|
||||
maxOccurrence(<span class="hl-number">3</span>)
|
||||
minOccurrence(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>)
|
||||
maxOccurrence(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>)
|
||||
})
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.valueWithMinEmpty'</span>, byType {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// results in verification of size of array (min 0)</span>
|
||||
minOccurrence(<span class="hl-number">0</span>)
|
||||
minOccurrence(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>)
|
||||
})
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.valueWithMaxEmpty'</span>, byType {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// results in verification of size of array (max 0)</span>
|
||||
maxOccurrence(<span class="hl-number">0</span>)
|
||||
maxOccurrence(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>)
|
||||
})
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// will execute a method `assertThatValueIsANumber`</span>
|
||||
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byCommand(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'assertThatValueIsANumber($it)'</span>))
|
||||
@@ -1522,14 +1522,14 @@ separates the autogenerated assertions and the assertion from matchers):</p><pre
|
||||
.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/get"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json.*"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['valueWithoutAMatcher']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.duck"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{3}"</span>);
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.duck"</span>, Integer.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).isEqualTo(<span class="hl-number">123</span>);
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.duck"</span>, Integer.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number>);
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.alpha"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[\\p{L}]*"</span>);
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.alpha"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"abc"</span>);
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.number"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"-?(\\d*\\.\\d+|\\d+)"</span>);
|
||||
@@ -1539,15 +1539,15 @@ separates the autogenerated assertions and the assertion from matchers):</p><pre
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.time"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])"</span>);
|
||||
assertThat((Object) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithTypeMatch"</span>)).isInstanceOf(java.lang.String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
assertThat((Object) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMin"</span>)).isInstanceOf(java.util.List.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMin"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMin"</span>).hasSizeGreaterThanOrEqualTo(<span class="hl-number">1</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMin"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMin"</span>).hasSizeGreaterThanOrEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>);
|
||||
assertThat((Object) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMax"</span>)).isInstanceOf(java.util.List.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMax"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMax"</span>).hasSizeLessThanOrEqualTo(<span class="hl-number">3</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMax"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMax"</span>).hasSizeLessThanOrEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>);
|
||||
assertThat((Object) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinMax"</span>)).isInstanceOf(java.util.List.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinMax"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinMax"</span>).hasSizeBetween(<span class="hl-number">1</span>, <span class="hl-number">3</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinMax"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinMax"</span>).hasSizeBetween(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>);
|
||||
assertThat((Object) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinEmpty"</span>)).isInstanceOf(java.util.List.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinEmpty"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinEmpty"</span>).hasSizeGreaterThanOrEqualTo(<span class="hl-number">0</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinEmpty"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMinEmpty"</span>).hasSizeGreaterThanOrEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>);
|
||||
assertThat((Object) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMaxEmpty"</span>)).isInstanceOf(java.util.List.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMaxEmpty"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMaxEmpty"</span>).hasSizeLessThanOrEqualTo(<span class="hl-number">0</span>);
|
||||
assertThat((java.lang.Iterable) parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMaxEmpty"</span>, java.util.Collection.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).as(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.valueWithMaxEmpty"</span>).hasSizeLessThanOrEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>);
|
||||
assertThatValueIsANumber(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.duck"</span>));
|
||||
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['key'].['complex.key']"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>);</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Notice that, for the <code class="literal">byCommand</code> method, the example calls the
|
||||
<code class="literal">assertThatValueIsANumber</code>. This method must be defined in the test base class or be
|
||||
@@ -1604,8 +1604,8 @@ the method name and passed the proper JSON path as a parameter to it.</p></td></
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>date\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>dateTime\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>T01:<span class="hl-number">23</span>:<span class="hl-number">45</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>aBoolean\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":true,\\"</span>valueWithMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithOccurrence\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3,4],\\"</span>number\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>duck\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>alpha\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>abc\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMin\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>time\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">01</span>:<span class="hl-number">02</span>:<span class="hl-number">34</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithTypeMatch\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>string\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMinMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithoutAMatcher\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>date\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2017</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>dateTime\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2017</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>T01:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">23</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">45</xslthl:number>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>aBoolean\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":true,\\"</span>valueWithMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithOccurrence\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3,4],\\"</span>number\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>duck\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>alpha\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>abc\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMin\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>time\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">02</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">34</xslthl:number>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithTypeMatch\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>string\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMinMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithoutAMatcher\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
@@ -1672,7 +1672,7 @@ content type set. Otherwise, the default of <code class="literal">application/oc
|
||||
String responseAsString = response.readEntity(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.getStatus()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.getStatus()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentContext parsedJson = JsonPath.parse(responseAsString);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['property1']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a"</span>);
|
||||
@@ -1700,9 +1700,9 @@ provide an <code class="literal">async()</code> method in the <code class="liter
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/get'</span>
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
|
||||
body <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Passed'</span>
|
||||
fixedDelayMilliseconds <span class="hl-number">1000</span>
|
||||
fixedDelayMilliseconds <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1000</xslthl:number>
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -1740,12 +1740,12 @@ socket.</p><p>Consider the following contract:</p><pre class="programlisting">or
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.boot.web.server.LocalServerPort;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(classes = ContextPathTestingBaseClass.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(classes = ContextPathTestingBaseClass.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ContextPathTestingBaseClass {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@LocalServerPort</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port;
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LocalServerPort</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssured.baseURI = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost"</span>;
|
||||
RestAssured.port = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.port;
|
||||
@@ -1772,10 +1772,10 @@ for WebFlux:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BeerRestBase {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssuredWebTestClient.standaloneSetup(
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ProducerController(personToCheck -> personToCheck.age >= <span class="hl-number">20</span>));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ProducerController(personToCheck -> personToCheck.age >= <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20</xslthl:number>));
|
||||
}
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_webflux_with_explicit_mode" href="#_webflux_with_explicit_mode"></a>8.9.2 WebFlux with Explicit mode</h3></div></div></div><p>Another way is with the <code class="literal">EXPLICIT</code> mode in your generated tests
|
||||
@@ -1793,25 +1793,25 @@ to work with WebFlux.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting">contracts {
|
||||
testMode = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'EXPLICIT'</span>
|
||||
}</pre><p class="secondary">
|
||||
</p><p>The following example shows how to set up a base class and Rest Assured for Web Flux:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(classes = BeerRestBase.Config.class,
|
||||
</p><p>The following example shows how to set up a base class and Rest Assured for Web Flux:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(classes = BeerRestBase.Config.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = "server.port=0")</span></em>
|
||||
properties = "server.port=0")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BeerRestBase {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// your tests go here</span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// in this config class you define all controllers and mocked services</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Config {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
PersonCheckingService personCheckingService() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> personToCheck -> personToCheck.age >= <span class="hl-number">20</span>;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> personToCheck -> personToCheck.age >= <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20</xslthl:number>;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
ProducerController producerController() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ProducerController(personCheckingService());
|
||||
}
|
||||
@@ -1837,18 +1837,18 @@ and the appropriate <code class="literal">MatchingType</code> as second. All the
|
||||
}
|
||||
body <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
|
||||
</span><test>
|
||||
<duck type=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'xtype'</span>><span class="hl-number">123</span></duck>
|
||||
<duck type=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'xtype'</span>><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number></duck>
|
||||
<alpha>abc</alpha>
|
||||
<list>
|
||||
<elem>abc</elem>
|
||||
<elem>def</elem>
|
||||
<elem>ghi</elem>
|
||||
</list>
|
||||
<number><span class="hl-number">123</span></number>
|
||||
<number><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123</xslthl:number></number>
|
||||
<aBoolean>true</aBoolean>
|
||||
<date><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span></date>
|
||||
<dateTime><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>T01:<span class="hl-number">23</span>:<span class="hl-number">45</span></dateTime>
|
||||
<time><span class="hl-number">01</span>:<span class="hl-number">02</span>:<span class="hl-number">34</span></time>
|
||||
<date><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2017</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number></date>
|
||||
<dateTime><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2017</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>T01:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">23</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">45</xslthl:number></dateTime>
|
||||
<time><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">01</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">02</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">34</xslthl:number></time>
|
||||
<valueWithoutAMatcher>foo</valueWithoutAMatcher>
|
||||
<key><complex>foo</complex></key>
|
||||
</test><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
|
||||
@@ -1867,7 +1867,7 @@ and the appropriate <code class="literal">MatchingType</code> as second. All the
|
||||
xPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/test/duck/@type'</span>, byEquality())
|
||||
}
|
||||
}
|
||||
}</pre><p>And below is an example of a YAML contract with XML request and response bodies:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">include</span>::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml</pre><p>Here is an example of an automatically generated test for XML response body:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
}</pre><p>And below is an example of a YAML contract with XML request and response bodies:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">include</span>::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml</pre><p>Here is an example of an automatically generated test for XML response body:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_xmlMatches() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
@@ -1877,7 +1877,7 @@ and the appropriate <code class="literal">MatchingType</code> as second. All the
|
||||
ResponseOptions response = given().spec(request).get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/get"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
|
||||
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
@@ -2078,7 +2078,7 @@ leads to generation of two tests that look more or less like this:</p><pre class
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> V1Test <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> TestBase {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_should_post_a_user() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given();
|
||||
@@ -2088,11 +2088,11 @@ leads to generation of two tests that look more or less like this:</p><pre class
|
||||
.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/users/1"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_withList_<span class="hl-number">1</span>() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_withList_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given();
|
||||
|
||||
@@ -2101,7 +2101,7 @@ leads to generation of two tests that look more or less like this:</p><pre class
|
||||
.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/users/2"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);
|
||||
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
|
||||
}
|
||||
|
||||
}</pre><p>Notice that, for the contract that has the <code class="literal">name</code> field, the generated test method is named
|
||||
@@ -2145,22 +2145,22 @@ testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest(classes = Application.class)</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(classes = Application.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FraudBaseWithWebAppSetup {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> String OUTPUT = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/generated-snippets"</span>;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Rule</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Rule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> JUnitRestDocumentation restDocumentation = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> JUnitRestDocumentation(OUTPUT);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Rule</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Rule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> TestName testName = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TestName();
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> WebApplicationContext context;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.context)
|
||||
.apply(documentationConfiguration(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.restDocumentation))
|
||||
@@ -2190,13 +2190,13 @@ testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> String OUTPUT = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/generated-snippets"</span>;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Rule</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Rule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> JUnitRestDocumentation restDocumentation = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> JUnitRestDocumentation(OUTPUT);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Rule</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Rule</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> TestName testName = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TestName();
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Before</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
|
||||
RestAssuredMockMvc.standaloneSetup(MockMvcBuilders
|
||||
.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudDetectionController())
|
||||
|
||||
@@ -9,14 +9,14 @@ That way the only remaining framework is Spring AMQP.</p></td></tr></table></div
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.Collection;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.Map;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Contract for triggering stub messages.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StubTrigger {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Triggers an event by a given label for a given {@code groupid:artifactid} notation.
|
||||
* You can use only {@code artifactId} too.
|
||||
*
|
||||
@@ -24,30 +24,30 @@ That way the only remaining framework is Spring AMQP.</p></td></tr></table></div
|
||||
* @param ivyNotation ivy notation of a stub
|
||||
* @param labelName name of the label to trigger
|
||||
* @return true - if managed to run a trigger
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger(String ivyNotation, String labelName);
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Triggers an event by a given label.
|
||||
*
|
||||
* Feature related to messaging.
|
||||
* @param labelName name of the label to trigger
|
||||
* @return true - if managed to run a trigger
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger(String labelName);
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Triggers all possible events.
|
||||
*
|
||||
* Feature related to messaging.
|
||||
* @return true - if managed to run a trigger
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger();
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
|
||||
* Feature related to messaging.
|
||||
* @return a mapping of ivy notation of a dependency to all the labels it has.
|
||||
*/</strong>
|
||||
*/</xslthl:doccomment>
|
||||
Map<String, Collection<String>> labels();
|
||||
|
||||
}</pre><p>For convenience, the <code class="literal">StubFinder</code> interface extends <code class="literal">StubTrigger</code>, so you only need one
|
||||
@@ -62,9 +62,9 @@ Remember to annotate your test class with <code class="literal">@AutoConfigureSt
|
||||
└── accurest
|
||||
└── stubs
|
||||
└── camelService
|
||||
├── <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
|
||||
│ ├── camelService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
|
||||
│ ├── camelService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
├── <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
|
||||
│ ├── camelService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
|
||||
│ ├── camelService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
│ └── maven-metadata-local.xml
|
||||
└── maven-metadata-local.xml</pre><p>And the stubs contain the following structure:</p><pre class="programlisting">├── META-INF
|
||||
│ └── MANIFEST.MF
|
||||
@@ -105,10 +105,10 @@ Remember to annotate your test class with <code class="literal">@AutoConfigureSt
|
||||
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
|
||||
}
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_scenario_1_no_input_message_2" href="#_scenario_1_no_input_message_2"></a>Scenario 1 (no input message)</h4></div></div></div><p>So as to trigger a message via the <code class="literal">return_book_1</code> label we’ll use the <code class="literal">StubTigger</code> interface as follows</p><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre><p>Next we’ll want to listen to the output of the message sent to <code class="literal">jms:output</code></p><pre class="programlisting">Exchange receivedMessage = consumerTemplate.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>, <span class="hl-number">5000</span>)</pre><p>And the received message would pass the following assertions</p><pre class="programlisting">receivedMessage != null
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_scenario_1_no_input_message_2" href="#_scenario_1_no_input_message_2"></a>Scenario 1 (no input message)</h4></div></div></div><p>So as to trigger a message via the <code class="literal">return_book_1</code> label we’ll use the <code class="literal">StubTigger</code> interface as follows</p><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre><p>Next we’ll want to listen to the output of the message sent to <code class="literal">jms:output</code></p><pre class="programlisting">Exchange receivedMessage = consumerTemplate.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>)</pre><p>And the received message would pass the following assertions</p><pre class="programlisting">receivedMessage != null
|
||||
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
|
||||
receivedMessage.in.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_scenario_2_output_triggered_by_input_2" href="#_scenario_2_output_triggered_by_input_2"></a>Scenario 2 (output triggered by input)</h4></div></div></div><p>Since the route is set for you it’s enough to just send a message to the <code class="literal">jms:output</code> destination.</p><pre class="programlisting">producerTemplate.
|
||||
sendBodyAndHeaders(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>])</pre><p>Next we’ll want to listen to the output of the message sent to <code class="literal">jms:output</code></p><pre class="programlisting">Exchange receivedMessage = consumerTemplate.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>, <span class="hl-number">5000</span>)</pre><p>And the received message would pass the following assertions</p><pre class="programlisting">receivedMessage != null
|
||||
sendBodyAndHeaders(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>])</pre><p>Next we’ll want to listen to the output of the message sent to <code class="literal">jms:output</code></p><pre class="programlisting">Exchange receivedMessage = consumerTemplate.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>)</pre><p>And the received message would pass the following assertions</p><pre class="programlisting">receivedMessage != null
|
||||
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
|
||||
receivedMessage.in.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_scenario_3_input_with_no_output" href="#_scenario_3_input_with_no_output"></a>Scenario 3 (input with no output)</h4></div></div></div><p>Since the route is set for you it’s enough to just send a message to the <code class="literal">jms:output</code> destination.</p><pre class="programlisting">producerTemplate.
|
||||
sendBodyAndHeaders(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:delete'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>])</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_integration" href="#_stub_runner_integration"></a>7.3 Stub Runner Integration</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner’s messaging module gives you an easy way to
|
||||
@@ -123,9 +123,9 @@ classpath. Remember to annotate your test class with <code class="literal">@Auto
|
||||
└── accurest
|
||||
└── stubs
|
||||
└── integrationService
|
||||
├── <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
|
||||
│ ├── integrationService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
|
||||
│ ├── integrationService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
├── <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
|
||||
│ ├── integrationService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
|
||||
│ ├── integrationService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
│ └── maven-metadata-local.xml
|
||||
└── maven-metadata-local.xml</pre><p>Further assume the stubs contain the following structure:</p><pre class="programlisting">├── META-INF
|
||||
│ └── MANIFEST.MF
|
||||
@@ -166,7 +166,7 @@ classpath. Remember to annotate your test class with <code class="literal">@Auto
|
||||
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
|
||||
}
|
||||
}
|
||||
}</pre><p>and the following Spring Integration Route:</p><pre class="programlisting"><span class="hl-directive" style="color: maroon"><?xml version="1.0" encoding="UTF-8"?></span>
|
||||
}</pre><p>and the following Spring Integration Route:</p><pre class="programlisting"><xslthl:directive xmlns:xslthl="http://xslthl.sourceforge.net/"><?xml version="1.0" encoding="UTF-8"?></xslthl:directive>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><beans:beans</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:beans</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/beans"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/integration"</span>
|
||||
@@ -213,9 +213,9 @@ property.</p><p>Assume that you have the following Maven repository with a deplo
|
||||
└── accurest
|
||||
└── stubs
|
||||
└── streamService
|
||||
├── <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
|
||||
│ ├── streamService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
|
||||
│ ├── streamService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
├── <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
|
||||
│ ├── streamService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
|
||||
│ ├── streamService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
│ └── maven-metadata-local.xml
|
||||
└── maven-metadata-local.xml</pre><p>Further assume the stubs contain the following structure:</p><pre class="programlisting">├── META-INF
|
||||
│ └── MANIFEST.MF
|
||||
@@ -249,7 +249,7 @@ property.</p><p>Assume that you have the following Maven repository with a deplo
|
||||
headers { header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>) }
|
||||
}
|
||||
}</pre><p>Now consider the following Spring configuration:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner.repositoryRoot</span>: classpath:m2repo/repository/
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner.ids</span>: org.springframework.cloud.contract.verifier.stubs:streamService:<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT:stubs
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner.ids</span>: org.springframework.cloud.contract.verifier.stubs:streamService:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT:stubs
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner.stubs-mode</span>: remote
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> cloud</span>:
|
||||
@@ -261,7 +261,7 @@ property.</p><p>Assume that you have the following Maven repository with a deplo
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> destination</span>: bookStorage
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">server</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">0</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">debug</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span></pre><p>These examples lend themselves to three scenarios:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#stream-scenario-1" title="Scenario 1 (no input message)">the section called “Scenario 1 (no input message)”</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#stream-scenario-2" title="Scenario 2 (output triggered by input)">the section called “Scenario 2 (output triggered by input)”</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#stream-scenario-3" title="Scenario 3 (input with no output)">the section called “Scenario 3 (input with no output)”</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="stream-scenario-1" href="#stream-scenario-1"></a>Scenario 1 (no input message)</h4></div></div></div><p>To trigger a message via the <code class="literal">return_book_1</code> label, use the <code class="literal">StubTrigger</code> interface as
|
||||
follows:</p><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre><p>To listen to the output of the message sent to a channel whose <code class="literal">destination</code> is
|
||||
@@ -294,9 +294,9 @@ to disable them explicitly by setting the <code class="literal">stubrunner.stre
|
||||
└── com
|
||||
└── example
|
||||
└── spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>
|
||||
├── <span class="hl-number">0.4</span>.<span class="hl-number">0</span>-SNAPSHOT
|
||||
│ ├── spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-<span class="hl-number">0.4</span>.<span class="hl-number">0</span>-SNAPSHOT.pom
|
||||
│ ├── spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-<span class="hl-number">0.4</span>.<span class="hl-number">0</span>-SNAPSHOT-stubs.jar
|
||||
├── <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT
|
||||
│ ├── spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT.pom
|
||||
│ ├── spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT-stubs.jar
|
||||
│ └── maven-metadata-local.xml
|
||||
└── maven-metadata-local.xml</pre><p>Further assume that the stubs contain the following structure:</p><pre class="programlisting">├── META-INF
|
||||
│ └── MANIFEST.MF
|
||||
@@ -321,25 +321,25 @@ to disable them explicitly by setting the <code class="literal">stubrunner.stre
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the body of the output message</span>
|
||||
body([
|
||||
id : $(consumer(<span class="hl-number">9</span>), producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]+"</span>))),
|
||||
id : $(consumer(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>), producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]+"</span>))),
|
||||
name: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"me"</span>
|
||||
])
|
||||
}
|
||||
}</pre><p>Now consider the following Spring configuration:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> repositoryRoot</span>: classpath:m2repo/repository/
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ids</span>: org.springframework.cloud.contract.verifier.stubs.amqp:spring-cloud-contract-amqp-test:<span class="hl-number">0.4</span>.<span class="hl-number">0</span>-SNAPSHOT:stubs
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ids</span>: org.springframework.cloud.contract.verifier.stubs.amqp:spring-cloud-contract-amqp-test:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT:stubs
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> stubs-mode</span>: remote
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> amqp</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> enabled</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">server</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">0</span></pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_triggering_the_message" href="#_triggering_the_message"></a>Triggering the message</h4></div></div></div><p>To trigger a message using the contract above, use the <code class="literal">StubTrigger</code> interface as
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number></pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_triggering_the_message" href="#_triggering_the_message"></a>Triggering the message</h4></div></div></div><p>To trigger a message using the contract above, use the <code class="literal">StubTrigger</code> interface as
|
||||
follows:</p><pre class="programlisting">stubTrigger.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"contract-test.person.created.event"</span>)</pre><p>The message has a destination of <code class="literal">contract-test.exchange</code>, so the Spring AMQP stub runner
|
||||
integration looks for bindings related to this exchange.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
integration looks for bindings related to this exchange.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Binding binding() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> BindingBuilder.bind(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Queue(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test.queue"</span>))
|
||||
.to(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> DirectExchange(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"contract-test.exchange"</span>)).with(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"#"</span>);
|
||||
}</pre><p>The binding definition binds the queue <code class="literal">test.queue</code>. As a result, the following listener
|
||||
definition is matched and invoked with the contract message.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
definition is matched and invoked with the contract message.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SimpleMessageListenerContainer simpleMessageListenerContainer(
|
||||
ConnectionFactory connectionFactory,
|
||||
MessageListenerAdapter listenerAdapter) {
|
||||
@@ -349,7 +349,7 @@ definition is matched and invoked with the contract message.</p><pre class="prog
|
||||
container.setMessageListener(listenerAdapter);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> container;
|
||||
}</pre><p>Also, the following annotated listener matches and is invoked:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RabbitListener(bindings = @QueueBinding(value = @Queue("test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))</span></em>
|
||||
}</pre><p>Also, the following annotated listener matches and is invoked:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RabbitListener(bindings = @QueueBinding(value = @Queue("test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> handlePerson(Person person) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.person = person;
|
||||
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The message is directly handed over to the <code class="literal">onMessage</code> method of the
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -272,7 +272,7 @@
|
||||
|
||||
<div class="section">
|
||||
<h2><a name="Checkstyle_Results"></a>Checkstyle Results</h2>
|
||||
<p>The following document contains the results of <a class="externalLink" href="http://checkstyle.sourceforge.net/">Checkstyle</a> 8.12 with sun_checks.xml ruleset. <a href="checkstyle.rss"><img alt="rss feed" src="images/rss.png" /></a></p></div>
|
||||
<p>The following document contains the results of <a class="externalLink" href="http://checkstyle.sourceforge.net/">Checkstyle</a> 8.18 with sun_checks.xml ruleset. <a href="checkstyle.rss"><img alt="rss feed" src="images/rss.png" /></a></p></div>
|
||||
<div class="section">
|
||||
<h2><a name="Summary"></a>Summary</h2>
|
||||
<table border="0" class="table table-striped">
|
||||
@@ -1773,7 +1773,7 @@
|
||||
<td>javadoc</td>
|
||||
<td>JavadocPackage</td>
|
||||
<td>Missing package-info.java file.</td>
|
||||
<td></td></tr>
|
||||
<td>1</td></tr>
|
||||
<tr class="b">
|
||||
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
|
||||
<td>sizes</td>
|
||||
@@ -3672,7 +3672,7 @@
|
||||
<td>javadoc</td>
|
||||
<td>JavadocPackage</td>
|
||||
<td>Missing package-info.java file.</td>
|
||||
<td></td></tr>
|
||||
<td>1</td></tr>
|
||||
<tr class="a">
|
||||
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
|
||||
<td>sizes</td>
|
||||
|
||||
@@ -332,7 +332,7 @@
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -340,8 +340,613 @@
|
||||
implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.</p>
|
||||
<p>Can't read the url [https://www.apache.org/licenses/LICENSE-2.0] : connect timed out</p></div></div>
|
||||
limitations under the License.</p><a class="externalLink" href="https://www.apache.org/licenses/LICENSE-2.0">[Original text]</a>
|
||||
<p>Copy of the license follows:</p>
|
||||
<!-- Navigation -->
|
||||
<header>
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top mainmenu">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#mainnav-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="mainnav-collapse">
|
||||
<ul class="nav navbar-nav navbar-justified">
|
||||
<li>
|
||||
<form class="visible-xs">
|
||||
<div class="input-group" style="width: 100%;">
|
||||
<script>
|
||||
(function() {
|
||||
var cx = '005703438322411770421:5mgshgrgx2u';
|
||||
var gcse = document.createElement('script');
|
||||
gcse.type = 'text/javascript';
|
||||
gcse.async = true;
|
||||
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
|
||||
'//cse.google.com/cse.js?cx=' + cx;
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(gcse, s);
|
||||
})();
|
||||
</script>
|
||||
<gcse:searchbox-only></gcse:searchbox-only>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
<li><a href="https://www.apache.org/index.html#news">News</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">About <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/foundation">Overview</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html">Process</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/governance/">Governance</a></li>
|
||||
<li><a href="https://www.apache.org/theapacheway/index.html">The Apache Way</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/governance/members.html">Membership</a></li>
|
||||
<li><a href="https://community.apache.org/">Community</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/glossary.html">Glossary</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/preFAQ.html">FAQ</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html">Support Apache</a></li>
|
||||
<li><a href="https://www.apache.org/press/">Media/Analysts</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contact.html">Contact</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Make a Donation <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html">Donate Now</a></li>
|
||||
<li><a href="https://donate.apache.org/"> Via Credit Card</a></li>
|
||||
<li><a href="https://donate.apache.org/"> Via ACH</a></li>
|
||||
<li><a href="https://donate.apache.org/"> Via PayPal</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html#Bitcoin"> Using Bigcoin</a></li>
|
||||
<li><a href="https://www.redbubble.com/people/comdev">Buy Swag</a></li>
|
||||
<li><a href="https://smile.amazon.com/gp/chpf/homepage/ref=smi_se_scyc_srch_stsr?q=apache+software+foundation&orig=%2F">Shop smile.amazon.com</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/sponsorship.html">ASF Sponsorship</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/thanks#targeted-sponsors">Targeted Sponsorship</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html#CorporateGiving">Corporate Giving</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdopwn-toggle" data-toggle="dropdown">The Apache Way <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/theapacheway/index.html">The Apache Way</a></li>
|
||||
<li><a href="https://s.apache.org/GhnI">Sustainable Open Source</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html">How it Works</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html#meritocracy">Merit</a></li>
|
||||
<li><a href="https://blogs.apache.org/foundation/category/SuccessAtApache">Success at Apache</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdopwn-toggle" data-toggle="dropdown">Join Us <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://community.apache.org/gettingStarted/101.html">Getting Started</a></li>
|
||||
<li><a href="https://helpwanted.apache.org/">Help Wanted</a></li>
|
||||
<li><a href="https://www.apachecon.com/">ApacheCon</a></li>
|
||||
<li><a href="http://community.apache.org/calendars/">Community Events</a></li>
|
||||
<li><a href="https://www.apache.org/travel/">Travel Assistance</a></li>
|
||||
<li><a href="https://community.apache.org/gsoc.html">Summer of Code</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a></li>
|
||||
<li><a href="https://community.apache.org/contributors/etiquette">Etiquette</a></li>
|
||||
<li class="dropdown dropdown-submenu visible-xs">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Projects <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/index.html#projects-list">Project List</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html#management">How they work</a></li>
|
||||
<li><a href="https://community.apache.org/projectIndependence.html">Independence</a></li>
|
||||
<li><a href="https://projects.apache.org/committees.html?date">Date Founded</a></li>
|
||||
<li><a href="https://projects.apache.org/projects.html?name">Names</a></li>
|
||||
<li><a href="https://projects.apache.org/projects.html?category">Categories</a></li>
|
||||
<li><a href="https://projects.apache.org/projects.html?language">Languages</a></li>
|
||||
<li><a href="https://projects.apache.org/statistics.html">Statistics</a></li>
|
||||
<li><a href="https://incubator.apache.org/">Apache Incubator</a></li>
|
||||
<li><a href="https://helpwanted.apache.org/">Help Wanted</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/marks/">Brand Management</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="drowpdown dropdown-submenu visible-xs">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">People <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html#roles">Roles</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/members.html">Members</a></li>
|
||||
<li><a href="https://community.apache.org/contributors/">Committers</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/#who-runs-the-asf">Board of Directors</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/#who-runs-the-asf">Officers & Project VPs</a></li>
|
||||
<li><a href="https://community.zones.apache.org/map.html">Location Map</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a></li>
|
||||
<li><a href="https://people.apache.org/">Committer Directory</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="drowpdown dropdown-submenu visible-xs">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Community <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://community.apache.org/about/">Community Development</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a></li>
|
||||
<li><a href="https://community.apache.org/">Get Involved</a></li>
|
||||
<li><a href="https://community.apache.org/mentoringprogramme.html">Mentoring</a></li>
|
||||
<li><a href="https://helpwanted.apache.org/">Help Wanted</a></li>
|
||||
<li><a href="https://community.apache.org/calendars/">Community Events</a></li>
|
||||
<li><a href="https://community.apache.org/newbiefaq.html">FAQ</a></li>
|
||||
<li><a href="https://community.apache.org/lists.html">Mailing Lists</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="drowpdown dropdown-submenu visible-xs">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">License <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/license-faq.html">Licensing FAQ</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/contributor-agreements.html">Contributor License Agreements</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/contributor-agreements.html#grants">Software Grants</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/marks/list/">Trademarks</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="drowpdown dropdown-submenu visible-xs">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Sponsors <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsor the ASF</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/thanks">Sponsor Thanks</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html#CorporateGiving">Corporate Giving</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html">Individual Donations</a></li>
|
||||
<li><a href="https://www.redbubble.com/people/comdev/">Buy Stuff</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Downloads <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/dist/">Distribution</a></li>
|
||||
<li><a href="https://projects.apache.org/releases.html">Releases</a></li>
|
||||
<li><a href="https://www.apache.org/dyn/closer.cgi">Mirrors</a></li>
|
||||
<li><a href="https://status.apache.org/">Infrastructure Status</a></li>
|
||||
<li><a href="https://www.apache.org/uptime/">Infrastructure Statistics</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown hidden-xs">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-search"
|
||||
aria-hidden="true"></span><span class="sr-only">Search</span></a>
|
||||
<ul class="dropdown-menu search-form" role="search">
|
||||
<li>
|
||||
<div class="input-group" style="width: 100%; padding: 0 5px;">
|
||||
<script>
|
||||
(function() {
|
||||
var cx = '005703438322411770421:5mgshgrgx2u';
|
||||
var gcse = document.createElement('script');
|
||||
gcse.type = 'text/javascript';
|
||||
gcse.async = true;
|
||||
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
|
||||
'//cse.google.com/cse.js?cx=' + cx;
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(gcse, s);
|
||||
})();
|
||||
</script>
|
||||
<gcse:searchbox-only></gcse:searchbox-only>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- / Navigation -->
|
||||
<header id="main-header" class="container">
|
||||
<div class="sideImg">
|
||||
<a class="visible-home" href="http://apachecon.com/"><img class="img-responsive" src="https://www.apache.org/img/ApacheCon-PROMO-2019.gif" alt="ApacheCon is Coming 9-12 Sept. 2019 - Las Vegas"></a>
|
||||
<a class="hidden-home" href="https://www.apache.org/"><img class="img-responsive" src="https://www.apache.org/img/ASF20thAnniversary.jpg" alt="The Apache Software Foundation"></a>
|
||||
</div>
|
||||
<div class="main">
|
||||
<img class="img-responsive center-block visible-home" src="https://www.apache.org/img/ASF20thAnniversary.jpg" alt="Apache 20th Anniversary Logo">
|
||||
<h2 class="text-center">Celebrating 20 years of community-led development "The Apache Way"</h2>
|
||||
<ul class="nav navbar-nav navbar-justified">
|
||||
<li class="drowpdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Projects <span class="caret hidden-sm"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/index.html#projects-list">Project List</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/#">How they work</a></li>
|
||||
<li><a href="https://community.apache.org/projectIndependence.html">Independence</a></li>
|
||||
<li><a href="https://projects.apache.org/committees.html?date">Date Founded</a></li>
|
||||
<li><a href="https://projects.apache.org/projects.html?name">Names</a></li>
|
||||
<li><a href="https://projects.apache.org/projects.html?category">Categories</a></li>
|
||||
<li><a href="https://projects.apache.org/projects.html?language">Languages</a></li>
|
||||
<li><a href="https://projects.apache.org/statistics.html">Statistics</a></li>
|
||||
<li><a href="https://incubator.apache.org/">Apache Incubator</a></li>
|
||||
<li><a href="https://helpwanted.apache.org/">Help Wanted</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/marks/">Brand Management</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/glossary.html">Glossary of Terms</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">People <span class="caret hidden-sm"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html#roles">Roles</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/members.html">Members</a></li>
|
||||
<li><a href="https://community.apache.org/contributors/">Committers</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/#who-runs-the-asf">Board of Directors</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/#who-runs-the-asf">Officers & Product VPs</a></li>
|
||||
<li><a href="https://community.zones.apache.org/map.html">Heat Map</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a></li>
|
||||
<li><a href="https://people.apache.org/">Committer Directory</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Community <span class="caret hidden-sm"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://community.apache.org/about/">Community Development</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a></li>
|
||||
<li><a href="https://community.apache.org/">Get Involved</a></li>
|
||||
<li><a href="https://community.apache.org/mentoringprogramme.html">Mentoring</a></li>
|
||||
<li><a href="https://helpwanted.apache.org/">Help Wanted</a></li>
|
||||
<li><a href="https://community.apache.org/calendars/">Community Events</a></li>
|
||||
<li><a href="https://community.apache.org/newbiefaq.html">FAQ</a></li>
|
||||
<li><a href="https://community.apache.org/lists.html">Mailing Lists</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">License <span class="caret hidden-sm"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/license-faq.html">Licensing FAQ</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/contributor-agreements.html">Contributor License Agreements</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/contributor-agreements.html#grants">Software Grants</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/marks/list/">Trademarks</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="https://www.apache.org/licenses/#" class="dropdown-toggle" data-toggle="dropdown">Sponsors <span class="caret hidden-sm"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsor the ASF</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/thanks">Sponsor Thanks</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html#CorporateGiving">Corporate Giving</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contributing.html">Individual Donations</a></li>
|
||||
<li><a href="https://www.redbubble.com/people/comdev/">Buy Stuff</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sideImg">
|
||||
<a href="https://www.apache.org/foundation/contributing.html"><img class="img-responsive" src="https://www.apache.org/img/support-apache.jpg" alt="Apache Support Logo" /></a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container"><style type="text/css">
|
||||
/* The following code is added by mdx_elementid.py
|
||||
It was originally lifted from http://subversion.apache.org/style/site.css */
|
||||
/*
|
||||
* Hide class="elementid-permalink", except when an enclosing heading
|
||||
* has the :hover property.
|
||||
*/
|
||||
.headerlink, .elementid-permalink {
|
||||
visibility: hidden;
|
||||
}
|
||||
h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
|
||||
<h3 id="apache-license-version-20">Apache License, Version 2.0<a class="headerlink" href="https://www.apache.org/licenses/#apache-license-version-20" title="Permanent link">¶</a></h3>
|
||||
<ul>
|
||||
<li>Text version: <a href="https://www.apache.org/licenses/LICENSE-2.0.txt">https://www.apache.org/licenses/LICENSE-2.0.txt</a></li>
|
||||
<li>SPDX short identifier: <a href="https://spdx.org/licenses/Apache-2.0.html">Apache-2.0</a></li>
|
||||
<li>OSI Approved License: <a href="https://opensource.org/licenses/Apache-2.0">https://opensource.org/licenses/Apache-2.0</a></li>
|
||||
</ul>
|
||||
<p>The 2.0 version of the Apache License, approved by the ASF in 2004, helps us achieve our goal of providing
|
||||
reliable and long-lived software products through collaborative open source software development. </p>
|
||||
<p>All packages produced by the ASF are implicitly licensed under the Apache
|
||||
License, Version 2.0, unless otherwise explicitly stated. </p>
|
||||
<div style="margin: 3em 10%; font-family:serif;text-align:justify; border: 1px solid black; padding: 2em; box-shadow: 4px 8px #888888;">
|
||||
|
||||
<p style="text-align:center">
|
||||
<strong>Apache License<br></br>Version 2.0, January 2004<br></br></strong>
|
||||
<strong><a href="http://www.apache.org/licenses/">http://www.apache.org/licenses/</a></strong>
|
||||
</p>
|
||||
|
||||
<p>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</p>
|
||||
|
||||
<p><strong><a name="definitions">1. Definitions</a></strong>.</p>
|
||||
|
||||
<div style="margin-left: 1em;">
|
||||
|
||||
<p>"<strong>License</strong>" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.</p>
|
||||
|
||||
<p>"<strong>Licensor</strong>" shall mean the copyright owner or entity authorized by the
|
||||
copyright owner that is granting the License.</p>
|
||||
|
||||
<p>"<strong>Legal Entity</strong>" shall mean the union of the acting entity and all other
|
||||
entities that control, are controlled by, or are under common control with
|
||||
that entity. For the purposes of this definition, "<strong>control</strong>" means (i) the
|
||||
power, direct or indirect, to cause the direction or management of such
|
||||
entity, whether by contract or otherwise, or (ii) ownership of fifty
|
||||
percent (50%) or more of the outstanding shares, or (iii) beneficial
|
||||
ownership of such entity.</p>
|
||||
|
||||
<p>"<strong>You</strong>" (or "<strong>Your</strong>") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.</p>
|
||||
|
||||
<p>"<strong>Source</strong>" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation source,
|
||||
and configuration files.</p>
|
||||
|
||||
<p>"<strong>Object</strong>" form shall mean any form resulting from mechanical transformation
|
||||
or translation of a Source form, including but not limited to compiled
|
||||
object code, generated documentation, and conversions to other media types.</p>
|
||||
|
||||
<p>"<strong>Work</strong>" shall mean the work of authorship, whether in Source or Object form,
|
||||
made available under the License, as indicated by a copyright notice that
|
||||
is included in or attached to the work (an example is provided in the
|
||||
Appendix below).</p>
|
||||
|
||||
<p>"<strong>Derivative Works</strong>" shall mean any work, whether in Source or Object form,
|
||||
that is based on (or derived from) the Work and for which the editorial
|
||||
revisions, annotations, elaborations, or other modifications represent, as
|
||||
a whole, an original work of authorship. For the purposes of this License,
|
||||
Derivative Works shall not include works that remain separable from, or
|
||||
merely link (or bind by name) to the interfaces of, the Work and Derivative
|
||||
Works thereof.</p>
|
||||
|
||||
<p>"<strong>Contribution</strong>" shall mean any work of authorship, including the original
|
||||
version of the Work and any modifications or additions to that Work or
|
||||
Derivative Works thereof, that is intentionally submitted to Licensor for
|
||||
inclusion in the Work by the copyright owner or by an individual or Legal
|
||||
Entity authorized to submit on behalf of the copyright owner. For the
|
||||
purposes of this definition, "<strong>submitted</strong>" means any form of electronic,
|
||||
verbal, or written communication sent to the Licensor or its
|
||||
representatives, including but not limited to communication on electronic
|
||||
mailing lists, source code control systems, and issue tracking systems that
|
||||
are managed by, or on behalf of, the Licensor for the purpose of discussing
|
||||
and improving the Work, but excluding communication that is conspicuously
|
||||
marked or otherwise designated in writing by the copyright owner as "<strong>Not a
|
||||
Contribution.</strong>"</p>
|
||||
|
||||
<p>"<strong>Contributor</strong>" shall mean Licensor and any individual or Legal Entity on
|
||||
behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<p><strong><a name="copyright">2. Grant of Copyright License</a></strong>. Subject to the
|
||||
terms and conditions of this License, each Contributor hereby grants to You
|
||||
a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of, publicly
|
||||
display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.</p>
|
||||
|
||||
<p><strong><a name="patent">3. Grant of Patent License</a></strong>. Subject to the terms
|
||||
and conditions of this License, each Contributor hereby grants to You a
|
||||
perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made, use,
|
||||
offer to sell, sell, import, and otherwise transfer the Work, where such
|
||||
license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by
|
||||
combination of their Contribution(s) with the Work to which such
|
||||
Contribution(s) was submitted. If You institute patent litigation against
|
||||
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that the Work or a Contribution incorporated within the Work constitutes
|
||||
direct or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate as of the
|
||||
date such litigation is filed.</p>
|
||||
|
||||
<p><strong><a name="redistribution">4. Redistribution</a></strong>. You may reproduce and
|
||||
distribute copies of the Work or Derivative Works thereof in any medium,
|
||||
with or without modifications, and in Source or Object form, provided that
|
||||
You meet the following conditions:</p>
|
||||
|
||||
<ol style="list-style: lower-latin;">
|
||||
<li>You must give any other recipients of the Work or Derivative Works a
|
||||
copy of this License; and</li>
|
||||
|
||||
<li>You must cause any modified files to carry prominent notices stating
|
||||
that You changed the files; and</li>
|
||||
|
||||
<li>You must retain, in the Source form of any Derivative Works that You
|
||||
distribute, all copyright, patent, trademark, and attribution notices from
|
||||
the Source form of the Work, excluding those notices that do not pertain to
|
||||
any part of the Derivative Works; and</li>
|
||||
|
||||
<li>If the Work includes a "<strong>NOTICE</strong>" text file as part of its distribution,
|
||||
then any Derivative Works that You distribute must include a readable copy
|
||||
of the attribution notices contained within such NOTICE file, excluding
|
||||
those notices that do not pertain to any part of the Derivative Works, in
|
||||
at least one of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or documentation,
|
||||
if provided along with the Derivative Works; or, within a display generated
|
||||
by the Derivative Works, if and wherever such third-party notices normally
|
||||
appear. The contents of the NOTICE file are for informational purposes only
|
||||
and do not modify the License. You may add Your own attribution notices
|
||||
within Derivative Works that You distribute, alongside or as an addendum to
|
||||
the NOTICE text from the Work, provided that such additional attribution
|
||||
notices cannot be construed as modifying the License.
|
||||
<br/>
|
||||
<br/>
|
||||
You may add Your own copyright statement to Your modifications and may
|
||||
provide additional or different license terms and conditions for use,
|
||||
reproduction, or distribution of Your modifications, or for any such
|
||||
Derivative Works as a whole, provided Your use, reproduction, and
|
||||
distribution of the Work otherwise complies with the conditions stated in
|
||||
this License.
|
||||
</li>
|
||||
|
||||
</ol>
|
||||
|
||||
<p><strong><a name="contributions">5. Submission of Contributions</a></strong>. Unless You
|
||||
explicitly state otherwise, any Contribution intentionally submitted for
|
||||
inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the
|
||||
terms of any separate license agreement you may have executed with Licensor
|
||||
regarding such Contributions.</p>
|
||||
|
||||
<p><strong><a name="trademarks">6. Trademarks</a></strong>. This License does not grant
|
||||
permission to use the trade names, trademarks, service marks, or product
|
||||
names of the Licensor, except as required for reasonable and customary use
|
||||
in describing the origin of the Work and reproducing the content of the
|
||||
NOTICE file.</p>
|
||||
|
||||
<p><strong><a name="no-warranty">7. Disclaimer of Warranty</a></strong>. Unless required by
|
||||
applicable law or agreed to in writing, Licensor provides the Work (and
|
||||
each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including,
|
||||
without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You
|
||||
are solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise
|
||||
of permissions under this License.</p>
|
||||
|
||||
<p><strong><a name="no-liability">8. Limitation of Liability</a></strong>. In no event and
|
||||
under no legal theory, whether in tort (including negligence), contract, or
|
||||
otherwise, unless required by applicable law (such as deliberate and
|
||||
grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a result
|
||||
of this License or out of the use or inability to use the Work (including
|
||||
but not limited to damages for loss of goodwill, work stoppage, computer
|
||||
failure or malfunction, or any and all other commercial damages or losses),
|
||||
even if such Contributor has been advised of the possibility of such
|
||||
damages.</p>
|
||||
|
||||
<p><strong><a name="additional">9. Accepting Warranty or Additional Liability</a></strong>.
|
||||
While redistributing the Work or Derivative Works thereof, You may choose
|
||||
to offer, and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this License.
|
||||
However, in accepting such obligations, You may act only on Your own behalf
|
||||
and on Your sole responsibility, not on behalf of any other Contributor,
|
||||
and only if You agree to indemnify, defend, and hold each Contributor
|
||||
harmless for any liability incurred by, or claims asserted against, such
|
||||
Contributor by reason of your accepting any such warranty or additional
|
||||
liability.</p>
|
||||
|
||||
<p>END OF TERMS AND CONDITIONS</p>
|
||||
|
||||
</div>
|
||||
|
||||
<h1 id="apply">How to apply the Apache License to your work<a class="headerlink" href="https://www.apache.org/licenses/#apply" title="Permanent link">¶</a></h1>
|
||||
<p>To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included
|
||||
on the same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.</p>
|
||||
<div class="codehilite"><pre>Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
</pre></div></div>
|
||||
|
||||
<!-- Footer -->
|
||||
|
||||
<footer class="bg-primary">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<br />
|
||||
<div class="col-sm-1">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h5 class="white">Community</h5>
|
||||
<ul class="list-unstyled white" role="menu">
|
||||
<li><a href="http://community.apache.org/">Overview</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/conferences.html">Conferences</a></li>
|
||||
<li><a href="http://community.apache.org/gsoc.html">Summer of Code</a></li>
|
||||
<li><a href="http://community.apache.org/newcomers/">Getting Started</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/how-it-works.html">The Apache Way</a></li>
|
||||
<li><a href="https://www.apache.org/travel/">Travel Assistance</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/getinvolved.html">Get Involved</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/conduct.html">Code of Conduct</a></li>
|
||||
<li><a href="http://community.apache.org/newbiefaq.html">Community FAQ</a></li>
|
||||
<li><a href="https://www.apache.org/memorials/">Memorials</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<h5 class="white">Innovation</h5>
|
||||
<ul class="list-unstyled white" role="menu">
|
||||
<li><a href="http://incubator.apache.org/">Incubator</a></li>
|
||||
<li><a href="http://labs.apache.org/">Labs</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/">Licensing</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/license-faq.html">Licensing FAQ</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/marks/">Trademark Policy</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contact.html">Contacts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<h5 class="white">Tech Operations</h5>
|
||||
<ul class="list-unstyled white" role="menu">
|
||||
<li><a href="https://www.apache.org/dev/">Developer Information</a></li>
|
||||
<li><a href="https://www.apache.org/dev/infrastructure.html">Infrastructure</a></li>
|
||||
<li><a href="https://www.apache.org/security/">Security</a></li>
|
||||
<li><a href="http://status.apache.org">Status</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contact.html">Contacts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<h5 class="white">Press</h5>
|
||||
<ul class="list-unstyled white" role="menu">
|
||||
<li><a href="https://www.apache.org/press/">Overview</a></li>
|
||||
<li><a href="https://blogs.apache.org/">ASF News</a></li>
|
||||
<li><a href="https://blogs.apache.org/foundation/">Announcements</a></li>
|
||||
<li><a href="https://twitter.com/TheASF">Twitter Feed</a></li>
|
||||
<li><a href="https://www.apache.org/press/#contact">Contacts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<h5 class="white">Legal</h5>
|
||||
<ul class="list-unstyled white" role="menu">
|
||||
<li><a href="https://www.apache.org/legal/">Legal Affairs</a></li>
|
||||
<li><a href="https://www.apache.org/legal/dmca.html">DMCA</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/">Licensing</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/marks/">Trademark Policy</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/records/">Public Records</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/policies/privacy.html">Privacy Policy</a></li>
|
||||
<li><a href="https://www.apache.org/licenses/exports/">Export Information</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/license-faq.html">Licensing FAQ</a></li>
|
||||
<li><a href="https://www.apache.org/foundation/contact.html">Contacts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-1">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr class="col-lg-12 hr-white" />
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<p class="text-center">Copyright © 2019 The Apache Software Foundation, Licensed under the <a class="white" href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
|
||||
<p class="text-center">Apache and the Apache feather logo are trademarks of The Apache Software Foundation. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</footer>
|
||||
|
||||
<!-- / Footer -->
|
||||
|
||||
<script src="/js/jquery-2.1.1.min.js"></script>
|
||||
<script src="/js/bootstrap.js"></script>
|
||||
<script>
|
||||
(function($){
|
||||
$(document).ready(function(){
|
||||
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(this).parent().siblings().removeClass('open');
|
||||
$(this).parent().toggleClass('open');
|
||||
console.log('WOrked');
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -329,7 +329,7 @@
|
||||
<tr class="b">
|
||||
<td>io.spring.javaformat</td>
|
||||
<td><a class="externalLink" href="https://github.com/spring-io/spring-javaformat/#/spring-javaformat-maven/spring-javaformat-maven-plugin">spring-javaformat-maven-plugin</a></td>
|
||||
<td>0.0.6</td></tr>
|
||||
<td>0.0.7</td></tr>
|
||||
<tr class="a">
|
||||
<td>org.apache.maven.plugins</td>
|
||||
<td><a class="externalLink" href="http://maven.apache.org/plugins/maven-antrun-plugin/">maven-antrun-plugin</a></td>
|
||||
@@ -401,7 +401,7 @@
|
||||
<tr class="b">
|
||||
<td>org.springframework.boot</td>
|
||||
<td><a class="externalLink" href="https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-tools/spring-boot-maven-plugin">spring-boot-maven-plugin</a></td>
|
||||
<td>2.1.3.RELEASE</td></tr>
|
||||
<td>2.1.6.RELEASE</td></tr>
|
||||
<tr class="a">
|
||||
<td>pl.project13.maven</td>
|
||||
<td><a class="externalLink" href="http://www.blog.project13.pl">git-commit-id-plugin</a></td>
|
||||
|
||||
@@ -329,7 +329,7 @@
|
||||
<tr class="b">
|
||||
<td>io.spring.javaformat</td>
|
||||
<td><a class="externalLink" href="https://github.com/spring-io/spring-javaformat/#/spring-javaformat-maven/spring-javaformat-maven-plugin">spring-javaformat-maven-plugin</a></td>
|
||||
<td>0.0.6</td></tr>
|
||||
<td>0.0.7</td></tr>
|
||||
<tr class="a">
|
||||
<td>io.takari.maven.plugins</td>
|
||||
<td><a class="externalLink" href="http://takari.io/takari-lifecycle/takari-lifecycle-plugin">takari-lifecycle-plugin</a></td>
|
||||
|
||||
@@ -5,430 +5,8 @@
|
||||
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Asciidoctor 1.5.7.1">
|
||||
<title>Untitled</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
||||
<style>
|
||||
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
|
||||
/* Uncomment @import statement below to use as custom stylesheet */
|
||||
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
|
||||
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
|
||||
audio,canvas,video{display:inline-block}
|
||||
audio:not([controls]){display:none;height:0}
|
||||
script{display:none!important}
|
||||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
|
||||
a{background:transparent}
|
||||
a:focus{outline:thin dotted}
|
||||
a:active,a:hover{outline:0}
|
||||
h1{font-size:2em;margin:.67em 0}
|
||||
abbr[title]{border-bottom:1px dotted}
|
||||
b,strong{font-weight:bold}
|
||||
dfn{font-style:italic}
|
||||
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
|
||||
mark{background:#ff0;color:#000}
|
||||
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
||||
pre{white-space:pre-wrap}
|
||||
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
||||
small{font-size:80%}
|
||||
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||
sup{top:-.5em}
|
||||
sub{bottom:-.25em}
|
||||
img{border:0}
|
||||
svg:not(:root){overflow:hidden}
|
||||
figure{margin:0}
|
||||
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
||||
legend{border:0;padding:0}
|
||||
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
||||
button,input{line-height:normal}
|
||||
button,select{text-transform:none}
|
||||
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
|
||||
button[disabled],html input[disabled]{cursor:default}
|
||||
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
|
||||
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||||
textarea{overflow:auto;vertical-align:top}
|
||||
table{border-collapse:collapse;border-spacing:0}
|
||||
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
html,body{font-size:100%}
|
||||
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
||||
a:hover{cursor:pointer}
|
||||
img,object,embed{max-width:100%;height:auto}
|
||||
object,embed{height:100%}
|
||||
img{-ms-interpolation-mode:bicubic}
|
||||
.left{float:left!important}
|
||||
.right{float:right!important}
|
||||
.text-left{text-align:left!important}
|
||||
.text-right{text-align:right!important}
|
||||
.text-center{text-align:center!important}
|
||||
.text-justify{text-align:justify!important}
|
||||
.hide{display:none}
|
||||
img,object,svg{display:inline-block;vertical-align:middle}
|
||||
textarea{height:auto;min-height:50px}
|
||||
select{width:100%}
|
||||
.center{margin-left:auto;margin-right:auto}
|
||||
.stretch{width:100%}
|
||||
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
||||
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
|
||||
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
||||
a:hover,a:focus{color:#1d4b8f}
|
||||
a img{border:none}
|
||||
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
||||
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
||||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
||||
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
||||
h1{font-size:2.125em}
|
||||
h2{font-size:1.6875em}
|
||||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
||||
h4,h5{font-size:1.125em}
|
||||
h6{font-size:1em}
|
||||
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
|
||||
em,i{font-style:italic;line-height:inherit}
|
||||
strong,b{font-weight:bold;line-height:inherit}
|
||||
small{font-size:60%;line-height:inherit}
|
||||
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
||||
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
||||
ul,ol{margin-left:1.5em}
|
||||
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
|
||||
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
|
||||
ul.square{list-style-type:square}
|
||||
ul.circle{list-style-type:circle}
|
||||
ul.disc{list-style-type:disc}
|
||||
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
||||
dl dt{margin-bottom:.3125em;font-weight:bold}
|
||||
dl dd{margin-bottom:1.25em}
|
||||
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
|
||||
abbr{text-transform:none}
|
||||
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
||||
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
|
||||
blockquote cite::before{content:"\2014 \0020"}
|
||||
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
|
||||
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
||||
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
||||
h1{font-size:2.75em}
|
||||
h2{font-size:2.3125em}
|
||||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
||||
h4{font-size:1.4375em}}
|
||||
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
|
||||
table thead,table tfoot{background:#f7f8f7}
|
||||
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||||
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
||||
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
|
||||
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
|
||||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
||||
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
||||
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
||||
.clearfix::after,.float-group::after{clear:both}
|
||||
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
|
||||
*:not(pre)>code.nobreak{word-wrap:normal}
|
||||
*:not(pre)>code.nowrap{white-space:nowrap}
|
||||
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
|
||||
em em{font-style:normal}
|
||||
strong strong{font-weight:400}
|
||||
.keyseq{color:rgba(51,51,51,.8)}
|
||||
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||
.keyseq kbd:first-child{margin-left:0}
|
||||
.keyseq kbd:last-child{margin-right:0}
|
||||
.menuseq,.menuref{color:#000}
|
||||
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
||||
.menuseq{word-spacing:-.02em}
|
||||
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
||||
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
||||
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
||||
b.button::before{content:"[";padding:0 3px 0 2px}
|
||||
b.button::after{content:"]";padding:0 2px 0 3px}
|
||||
p a>code:hover{color:rgba(0,0,0,.9)}
|
||||
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
||||
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
||||
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
||||
#content{margin-top:1.25em}
|
||||
#content::before{content:none}
|
||||
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
||||
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
|
||||
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
|
||||
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
|
||||
#header .details span:first-child{margin-left:-.125em}
|
||||
#header .details span.email a{color:rgba(0,0,0,.85)}
|
||||
#header .details br{display:none}
|
||||
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
||||
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
||||
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
||||
#header #revnumber{text-transform:capitalize}
|
||||
#header #revnumber::after{content:"\00a0"}
|
||||
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
||||
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
|
||||
#toc>ul{margin-left:.125em}
|
||||
#toc ul.sectlevel0>li>a{font-style:italic}
|
||||
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
||||
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
||||
#toc li{line-height:1.3334;margin-top:.3334em}
|
||||
#toc a{text-decoration:none}
|
||||
#toc a:active{text-decoration:underline}
|
||||
#toctitle{color:#7a2518;font-size:1.2em}
|
||||
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
||||
body.toc2{padding-left:15em;padding-right:0}
|
||||
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
||||
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||||
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
||||
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
||||
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
||||
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
|
||||
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
||||
#toc.toc2{width:20em}
|
||||
#toc.toc2 #toctitle{font-size:1.375em}
|
||||
#toc.toc2>ul{font-size:.95em}
|
||||
#toc.toc2 ul ul{padding-left:1.25em}
|
||||
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
||||
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
||||
#content #toc>:first-child{margin-top:0}
|
||||
#content #toc>:last-child{margin-bottom:0}
|
||||
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
|
||||
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
|
||||
#content{margin-bottom:.625em}
|
||||
.sect1{padding-bottom:.625em}
|
||||
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
||||
.sect1{padding-bottom:1.25em}}
|
||||
.sect1:last-child{padding-bottom:0}
|
||||
.sect1+.sect1{border-top:1px solid #efefed}
|
||||
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
||||
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
||||
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
||||
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
||||
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
||||
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
||||
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
||||
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
||||
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
||||
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
|
||||
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
||||
.admonitionblock>table td.icon{text-align:center;width:80px}
|
||||
.admonitionblock>table td.icon img{max-width:none}
|
||||
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
||||
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
|
||||
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
||||
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
|
||||
.exampleblock>.content>:first-child{margin-top:0}
|
||||
.exampleblock>.content>:last-child{margin-bottom:0}
|
||||
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
||||
.sidebarblock>:first-child{margin-top:0}
|
||||
.sidebarblock>:last-child{margin-bottom:0}
|
||||
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
||||
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||||
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
|
||||
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
|
||||
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
|
||||
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
|
||||
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
|
||||
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
|
||||
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
|
||||
.listingblock pre.highlightjs{padding:0}
|
||||
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
|
||||
.listingblock pre.prettyprint{border-width:0}
|
||||
.listingblock>.content{position:relative}
|
||||
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
|
||||
.listingblock:hover code[data-lang]::before{display:block}
|
||||
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
|
||||
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
||||
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
||||
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
|
||||
table.pyhltable td.code{padding-left:.75em;padding-right:0}
|
||||
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
|
||||
pre.pygments .lineno{display:inline-block;margin-right:.25em}
|
||||
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
|
||||
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
||||
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
|
||||
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
||||
.quoteblock blockquote{margin:0;padding:0;border:0}
|
||||
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
||||
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
||||
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
|
||||
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
|
||||
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
|
||||
.quoteblock .quoteblock blockquote::before{display:none}
|
||||
.verseblock{margin:0 1em 1.25em}
|
||||
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||||
.verseblock pre strong{font-weight:400}
|
||||
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
||||
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
||||
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
||||
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
||||
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
||||
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
||||
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6}
|
||||
.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none}
|
||||
table.tableblock{max-width:100%;border-collapse:separate}
|
||||
p.tableblock:last-child{margin-bottom:0}
|
||||
td.tableblock>.content{margin-bottom:-1.25em}
|
||||
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
||||
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
|
||||
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
|
||||
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
|
||||
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
|
||||
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
|
||||
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
|
||||
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
|
||||
table.frame-all{border-width:1px}
|
||||
table.frame-sides{border-width:0 1px}
|
||||
table.frame-topbot,table.frame-ends{border-width:1px 0}
|
||||
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
|
||||
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
|
||||
th.halign-left,td.halign-left{text-align:left}
|
||||
th.halign-right,td.halign-right{text-align:right}
|
||||
th.halign-center,td.halign-center{text-align:center}
|
||||
th.valign-top,td.valign-top{vertical-align:top}
|
||||
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
||||
th.valign-middle,td.valign-middle{vertical-align:middle}
|
||||
table thead th,table tfoot th{font-weight:bold}
|
||||
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
|
||||
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
||||
p.tableblock>code:only-child{background:none;padding:0}
|
||||
p.tableblock{font-size:1em}
|
||||
td>div.verse{white-space:pre}
|
||||
ol{margin-left:1.75em}
|
||||
ul li ol{margin-left:1.5em}
|
||||
dl dd{margin-left:1.125em}
|
||||
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
||||
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
||||
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
||||
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
||||
ul.unstyled,ol.unstyled{margin-left:0}
|
||||
ul.checklist{margin-left:.625em}
|
||||
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
||||
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
|
||||
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
||||
ul.inline>li{margin-left:1.25em}
|
||||
.unstyled dl dt{font-weight:400;font-style:normal}
|
||||
ol.arabic{list-style-type:decimal}
|
||||
ol.decimal{list-style-type:decimal-leading-zero}
|
||||
ol.loweralpha{list-style-type:lower-alpha}
|
||||
ol.upperalpha{list-style-type:upper-alpha}
|
||||
ol.lowerroman{list-style-type:lower-roman}
|
||||
ol.upperroman{list-style-type:upper-roman}
|
||||
ol.lowergreek{list-style-type:lower-greek}
|
||||
.hdlist>table,.colist>table{border:0;background:none}
|
||||
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
||||
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
||||
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
||||
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
||||
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
||||
.colist td:not([class]):first-child img{max-width:none}
|
||||
.colist td:not([class]):last-child{padding:.25em 0}
|
||||
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
|
||||
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
|
||||
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
|
||||
.imageblock>.title{margin-bottom:0}
|
||||
.imageblock.thumb,.imageblock.th{border-width:6px}
|
||||
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
||||
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
||||
.image.left{margin-right:.625em}
|
||||
.image.right{margin-left:.625em}
|
||||
a.image{text-decoration:none;display:inline-block}
|
||||
a.image object{pointer-events:none}
|
||||
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
||||
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||||
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
|
||||
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
||||
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
||||
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
||||
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
||||
#footnotes .footnote:last-of-type{margin-bottom:0}
|
||||
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
||||
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
|
||||
.gist .file-data>table td.line-data{width:99%}
|
||||
div.unbreakable{page-break-inside:avoid}
|
||||
.big{font-size:larger}
|
||||
.small{font-size:smaller}
|
||||
.underline{text-decoration:underline}
|
||||
.overline{text-decoration:overline}
|
||||
.line-through{text-decoration:line-through}
|
||||
.aqua{color:#00bfbf}
|
||||
.aqua-background{background-color:#00fafa}
|
||||
.black{color:#000}
|
||||
.black-background{background-color:#000}
|
||||
.blue{color:#0000bf}
|
||||
.blue-background{background-color:#0000fa}
|
||||
.fuchsia{color:#bf00bf}
|
||||
.fuchsia-background{background-color:#fa00fa}
|
||||
.gray{color:#606060}
|
||||
.gray-background{background-color:#7d7d7d}
|
||||
.green{color:#006000}
|
||||
.green-background{background-color:#007d00}
|
||||
.lime{color:#00bf00}
|
||||
.lime-background{background-color:#00fa00}
|
||||
.maroon{color:#600000}
|
||||
.maroon-background{background-color:#7d0000}
|
||||
.navy{color:#000060}
|
||||
.navy-background{background-color:#00007d}
|
||||
.olive{color:#606000}
|
||||
.olive-background{background-color:#7d7d00}
|
||||
.purple{color:#600060}
|
||||
.purple-background{background-color:#7d007d}
|
||||
.red{color:#bf0000}
|
||||
.red-background{background-color:#fa0000}
|
||||
.silver{color:#909090}
|
||||
.silver-background{background-color:#bcbcbc}
|
||||
.teal{color:#006060}
|
||||
.teal-background{background-color:#007d7d}
|
||||
.white{color:#bfbfbf}
|
||||
.white-background{background-color:#fafafa}
|
||||
.yellow{color:#bfbf00}
|
||||
.yellow-background{background-color:#fafa00}
|
||||
span.icon>.fa{cursor:default}
|
||||
a span.icon>.fa{cursor:inherit}
|
||||
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
||||
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
||||
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
||||
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
||||
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
||||
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
||||
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||
.conum[data-value] *{color:#fff!important}
|
||||
.conum[data-value]+b{display:none}
|
||||
.conum[data-value]::after{content:attr(data-value)}
|
||||
pre .conum[data-value]{position:relative;top:-.125em}
|
||||
b.conum *{color:inherit!important}
|
||||
.conum:not([data-value]):empty{display:none}
|
||||
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
||||
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
|
||||
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
||||
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
|
||||
p{margin-bottom:1.25rem}
|
||||
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
||||
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
||||
.print-only{display:none!important}
|
||||
@page{margin:1.25cm .75cm}
|
||||
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
|
||||
html{font-size:80%}
|
||||
a{color:inherit!important;text-decoration:underline!important}
|
||||
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
||||
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
||||
abbr[title]::after{content:" (" attr(title) ")"}
|
||||
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
||||
thead{display:table-header-group}
|
||||
svg{max-width:100%}
|
||||
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
||||
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
||||
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
||||
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
|
||||
body.book #header{text-align:center}
|
||||
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
||||
body.book #header .details{border:0!important;display:block;padding:0!important}
|
||||
body.book #header .details span:first-child{margin-left:0!important}
|
||||
body.book #header .details br{display:block}
|
||||
body.book #header .details br+span::before{content:none!important}
|
||||
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
||||
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
||||
.listingblock code[data-lang]::before{display:block}
|
||||
#footer{padding:0 .9375em}
|
||||
.hide-on-print{display:none!important}
|
||||
.print-only{display:block!important}
|
||||
.hide-for-print{display:none!important}
|
||||
.show-for-print{display:inherit!important}}
|
||||
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
|
||||
.sect1{padding:0!important}
|
||||
.sect1+.sect1{border:0}
|
||||
#footer{background:none}
|
||||
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
||||
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
||||
</style>
|
||||
<title>spring-cloud-contract</title>
|
||||
<link rel="stylesheet" href="css/manual-singlepage.css">
|
||||
<style>
|
||||
.hidden {
|
||||
display: none;
|
||||
@@ -506,43 +84,32 @@ $(addBlockSwitches);
|
||||
|
||||
<body class="article">
|
||||
<div id="header">
|
||||
<h1>spring-cloud-contract</h1>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div class="literalblock">
|
||||
<div class="content">
|
||||
<pre>:linkcss:
|
||||
:stylesdir: css
|
||||
:stylesheet: manual-singlepage.css</pre>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>2.1.2.BUILD-SNAPSHOT</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="literalblock">
|
||||
<div class="content">
|
||||
<pre>= {docs-main}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="literalblock">
|
||||
<div class="content">
|
||||
<pre>{spring-cloud-version}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="literalblock">
|
||||
<div class="content">
|
||||
<pre>== Pick The Documentation Option</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="single/spring-cloud-contract.html">Single
|
||||
HTML</a></p>
|
||||
<p><a href="single/spring-cloud-contract.html">Single HTML</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="multi/multi_spring-cloud-contract.html">Multi
|
||||
HTML</a></p>
|
||||
<p><a href="multi/multi_spring-cloud-contract.html">Multi HTML</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
|
||||
<script>prettyPrint()</script>
|
||||
|
||||
Reference in New Issue
Block a user