Sync docs from 2.0.x to gh-pages

This commit is contained in:
buildmaster
2018-08-22 15:30:44 +00:00
parent 41eee04415
commit 4c00f694f3
11 changed files with 2301 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>9.&nbsp;Customization</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__contract_dsl.html" title="8.&nbsp;Contract DSL"><link rel="next" href="multi__using_the_pluggable_architecture.html" title="10.&nbsp;Using the Pluggable Architecture"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9.&nbsp;Customization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customization" href="#_customization"></a>9.&nbsp;Customization</h1></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</p></td></tr></table></div><p>You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in
<title>9.&nbsp;Customization</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi_contract-dsl.html" title="8.&nbsp;Contract DSL"><link rel="next" href="multi__using_the_pluggable_architecture.html" title="10.&nbsp;Using the Pluggable Architecture"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9.&nbsp;Customization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_contract-dsl.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customization" href="#_customization"></a>9.&nbsp;Customization</h1></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</p></td></tr></table></div><p>You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in
the remainder of this section.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_extending_the_dsl" href="#_extending_the_dsl"></a>9.1&nbsp;Extending the DSL</h2></div></div></div><p>You can provide your own functions to the DSL. The key requirement for this feature is to
maintain the static compatibility. Later in this document, you can see examples of:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Creating a JAR with reusable classes.</li><li class="listitem">Referencing of these classes in the DSLs.</li></ul></div><p>You can find the full example
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples" target="_top">here</a>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_common_jar" href="#_common_jar"></a>9.1.1&nbsp;Common JAR</h3></div></div></div><p>The following examples show three classes that can be reused in the DSLs.</p><p><span class="strong"><strong>PatternUtils</strong></span> contains functions used by both the <span class="strong"><strong>consumer</strong></span> and the <span class="strong"><strong>producer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
@@ -214,4 +214,4 @@ then:
contentType(applicationJson())
}
}
}</pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8.&nbsp;Contract DSL&nbsp;</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">&nbsp;10.&nbsp;Using the Pluggable Architecture</td></tr></table></div></body></html>
}</pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_contract-dsl.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8.&nbsp;Contract DSL&nbsp;</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">&nbsp;10.&nbsp;Using the Pluggable Architecture</td></tr></table></div></body></html>

View File

@@ -45,7 +45,7 @@ sides of the communication. You can pass the values:</p><p>Either via the <code
value(stub(...), test(...))
value(client(...), server(...))</pre><p>or using the <code class="literal">$()</code> method</p><pre class="programlisting">$(consumer(...), producer(...))
$(stub(...), test(...))
$(client(...), server(...))</pre><p>You can read more about this in the <a class="xref" href="">???</a> section.</p><p>Calling <code class="literal">value()</code> or <code class="literal">$()</code> tells Spring Cloud Contract that you will be passing a dynamic value.
$(client(...), server(...))</pre><p>You can read more about this in the <a class="xref" href="multi_contract-dsl.html" title="8.&nbsp;Contract DSL">Chapter&nbsp;8, <i>Contract DSL</i></a> section.</p><p>Calling <code class="literal">value()</code> or <code class="literal">$()</code> tells Spring Cloud Contract that you will be passing a dynamic value.
Inside the <code class="literal">consumer()</code> method you pass the value that should be used on the consumer side (in the generated stub).
Inside the <code class="literal">producer()</code> method you pass the value that should be used on the producer side (in the generated test).</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>If on one side you have passed the regular expression and you haven&#8217;t passed the other, then the
other side will get auto-generated.</p></td></tr></table></div><p>Most often you will use that method together with the <code class="literal">regex</code> helper method. E.g. <code class="literal">consumer(regex('[0-9]{10}'))</code>.</p><p>To sum it up the contract for the aforementioned scenario would look more or less like this (the regular expression
@@ -82,7 +82,7 @@ It can be related to security issues where the consumers can&#8217;t clone the p
contracts in a single place then you, as a producer, will know how many consumers you have and which
consumer will you break with your local changes.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_repo_structure" href="#_repo_structure"></a>3.5.1&nbsp;Repo structure</h3></div></div></div><p>Let&#8217;s assume that we have a producer with coordinates <code class="literal">com.example:server</code> and 3 consumers: <code class="literal">client1</code>,
<code class="literal">client2</code>, <code class="literal">client3</code>. Then in the repository with common contracts you would have the following setup
(which you can checkout <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/contracts" target="_top">here</a>):</p><pre class="programlisting">&#9500;&#9472;&#9472; com
(which you can checkout <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/2.0.x/samples/standalone/contracts" target="_top">here</a>):</p><pre class="programlisting">&#9500;&#9472;&#9472; com
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; example
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; server
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; client1
@@ -115,14 +115,14 @@ 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">&lt;parent&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>2.0.3.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>2.0.4.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;relativePath /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/parent&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/project.build.sourceEncoding&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;java.version&gt;</span>1.8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/java.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring-cloud-contract.version&gt;</span>2.1.0.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring-cloud-contract.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring-cloud-contract.version&gt;</span>2.0.2.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring-cloud-contract.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring-cloud-release.version&gt;</span>Finchley.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring-cloud-release.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;excludeBuildFolders&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/excludeBuildFolders&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/properties&gt;</span>
@@ -399,7 +399,7 @@ build.dependsOn(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">
Artifactory or Nexus. Starting from Spring Cloud Contract version 2.0.0 we provide
mechanisms to store contracts and stubs in a SCM repository. Currently the
only supported SCM is Git.</p><p>The repository would have to the following setup
(which you can checkout <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/contracts_git/" target="_top">here</a>):</p><pre class="screen">.
(which you can checkout <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/contracts_git/" target="_top">here</a>):</p><pre class="screen">.
&#9492;&#9472;&#9472; META-INF
&#9492;&#9472;&#9472; com.example
&#9492;&#9472;&#9472; beer-api-producer-git
@@ -515,11 +515,11 @@ shares the files with the Producer. Those expectations are generated
from the Consumer&#8217;s code and can break the Producer if the expectation
is not met.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_consumer" href="#_pact_consumer"></a>3.7.1&nbsp;Pact Consumer</h3></div></div></div><p>The consumer uses Pact framework to generate Pact files. The
Pact files are sent to the Pact Broker. An example of such
setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/consumer_pact" target="_top">here</a>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_3" href="#_producer_3"></a>3.7.2&nbsp;Producer</h3></div></div></div><p>For the producer, to use the Pact files from the Pact Broker, we can reuse the
setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_pact" target="_top">here</a>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_3" href="#_producer_3"></a>3.7.2&nbsp;Producer</h3></div></div></div><p>For the producer, to use the Pact files from the Pact Broker, we can reuse the
same mechanism we use for external contracts. We route Spring Cloud Contract
to use the Pact implementation via the URL that contains
the <code class="literal">pact://</code> protocol. It&#8217;s enough to pass the URL to the
Pact Broker. An example of such setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/producer_pact" target="_top">here</a>.</p><p><b>Maven.&nbsp;</b>
Pact Broker. An example of such setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_pact" target="_top">here</a>.</p><p><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
@@ -582,7 +582,7 @@ contracts {
(for every single consumer define the expectations) but you&#8217;d prefer
to do Producer Contracts (the producer provides the contracts and
publishes stubs), it&#8217;s enough to use Spring Cloud Contract with
Stub Runner option. An example of such setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/consumer_pact_stubrunner" target="_top">here</a>.</p><p>First, remember to add Stub Runner and Spring Cloud Contract Pact module
Stub Runner option. An example of such setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_pact_stubrunner" target="_top">here</a>.</p><p>First, remember to add Stub Runner and Spring Cloud Contract Pact module
as test dependencies.</p><p><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>

View File

@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>6.&nbsp;Spring Cloud Contract Stub Runner</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_verifier_messaging.html" title="5.&nbsp;Spring Cloud Contract Verifier Messaging"><link rel="next" href="multi__stub_runner_for_messaging.html" title="7.&nbsp;Stub Runner for Messaging"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.&nbsp;Spring Cloud Contract Stub Runner</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_messaging.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__stub_runner_for_messaging.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_stub_runner" href="#_spring_cloud_contract_stub_runner"></a>6.&nbsp;Spring Cloud Contract Stub Runner</h1></div></div></div><p>One of the issues that you might encounter while using Spring Cloud Contract Verifier is
<title>6.&nbsp;Spring Cloud Contract Stub Runner</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_verifier_messaging.html" title="5.&nbsp;Spring Cloud Contract Verifier Messaging"><link rel="next" href="multi_stub-runner-for-messaging.html" title="7.&nbsp;Stub Runner for Messaging"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.&nbsp;Spring Cloud Contract Stub Runner</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_messaging.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_stub-runner-for-messaging.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_stub_runner" href="#_spring_cloud_contract_stub_runner"></a>6.&nbsp;Spring Cloud Contract Stub Runner</h1></div></div></div><p>One of the issues that you might encounter while using Spring Cloud Contract Verifier is
passing the generated WireMock JSON stubs from the server side to the client side (or to
various clients). The same takes place in terms of client-side generation for messaging.</p><p>Copying the JSON files and setting the client side for messaging manually is out of the
question. That is why we introduced Spring Cloud Contract Stub Runner. It can
@@ -732,4 +732,4 @@ $ curl -H <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Conte
$ curl -X GET http://localhost:<span class="hl-number">9876</span>/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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__stub_runner_for_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.&nbsp;Spring Cloud Contract Verifier Messaging&nbsp;</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">&nbsp;7.&nbsp;Stub Runner for Messaging</td></tr></table></div></body></html>
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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_stub-runner-for-messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.&nbsp;Spring Cloud Contract Verifier Messaging&nbsp;</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">&nbsp;7.&nbsp;Stub Runner for Messaging</td></tr></table></div></body></html>

View File

@@ -9,14 +9,14 @@ produced by Spring Cloud Contract Verifier.</li><li class="listitem">Messaging r
Integration, Spring Cloud Stream, Spring AMQP, and Apache Camel. You can also set your
own integrations.</li><li class="listitem">Acceptance tests (in JUnit or Spock) are used to verify if server-side implementation
of the API is compliant with the contract (<span class="emphasis"><em>server tests</em></span>). A full test is generated by
Spring Cloud Contract Verifier.</li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_a_contract_verifier" href="#_why_a_contract_verifier"></a>2.1&nbsp;Why a Contract Verifier?</h2></div></div></div><p>Assume that we have a system consisting of multiple microservices:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/Deps.png" alt="Microservices Architecture"></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_testing_issues" href="#_testing_issues"></a>2.1.1&nbsp;Testing issues</h3></div></div></div><p>If we wanted to test the application in top left corner to determine whether it can
Spring Cloud Contract Verifier.</li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_a_contract_verifier" href="#_why_a_contract_verifier"></a>2.1&nbsp;Why a Contract Verifier?</h2></div></div></div><p>Assume that we have a system consisting of multiple microservices:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.0.x/docs/src/main/asciidoc/images/Deps.png" alt="Microservices Architecture"></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_testing_issues" href="#_testing_issues"></a>2.1.1&nbsp;Testing issues</h3></div></div></div><p>If we wanted to test the application in top left corner to determine whether it can
communicate with other services, we could do one of two things:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Deploy all microservices and perform end-to-end tests.</li><li class="listitem">Mock other microservices in unit/integration tests.</li></ul></div><p>Both have their advantages but also a lot of disadvantages.</p><p><span class="strong"><strong>Deploy all microservices and perform end to end tests</strong></span></p><p>Advantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Simulates production.</li><li class="listitem">Tests real communication between services.</li></ul></div><p>Disadvantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">To test one microservice, we have to deploy 6 microservices, a couple of databases,
etc.</li><li class="listitem">The environment where the tests run is locked for a single suite of tests (nobody else
would be able to run the tests in the meantime).</li><li class="listitem">They take a long time to run.</li><li class="listitem">The feedback comes very late in the process.</li><li class="listitem">They are extremely hard to debug.</li></ul></div><p><span class="strong"><strong>Mock other microservices in unit/integration tests</strong></span></p><p>Advantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">They provide very fast feedback.</li><li class="listitem">They have no infrastructure requirements.</li></ul></div><p>Disadvantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The implementor of the service creates stubs that might have nothing to do with
reality.</li><li class="listitem">You can go to production with passing tests and failing production.</li></ul></div><p>To solve the aforementioned issues, Spring Cloud Contract Verifier with Stub Runner was
created. The main idea is to give you very fast feedback, without the need to set up the
whole world of microservices. If you work on stubs, then the only applications you need
are those that your application directly uses.</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/Stubs2.png" alt="Stubbed Services"></div></div><p>Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were
are those that your application directly uses.</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.0.x/docs/src/main/asciidoc/images/Stubs2.png" alt="Stubbed Services"></div></div><p>Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were
created by the service that you&#8217;re calling. Also, if you can use them, it means that they
were tested against the producer&#8217;s side. In short, you can trust those stubs.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_purposes" href="#_purposes"></a>2.2&nbsp;Purposes</h2></div></div></div><p>The main purposes of Spring Cloud Contract Verifier with Stub Runner are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">To ensure that WireMock/Messaging stubs (used when developing the client) do exactly
what the actual server-side implementation does.</li><li class="listitem">To promote ATDD method and Microservices architectural style.</li><li class="listitem">To provide a way to publish changes in contracts that are immediately visible on both
@@ -390,8 +390,8 @@ us. The current implementation of our system grants loans to everybody.</p><p>As
sprint, we must develop a new feature: if a client wants to borrow too much money, then
we mark the client as a fraud.</p><p>Technical remark - Fraud Detection has an <code class="literal">artifact-id</code> of <code class="literal">http-server</code>, while Loan
Issuance has an artifact-id of <code class="literal">http-client</code>, and both have a <code class="literal">group-id</code> of <code class="literal">com.example</code>.</p><p>Social remark - both client and server development teams need to communicate directly and
discuss changes while going through the process. CDC is all about communication.</p><p>The <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/dsl/http-server" target="_top">server
side code is available here</a> and <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/dsl/http-client" target="_top">the
discuss changes while going through the process. CDC is all about communication.</p><p>The <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/2.0.x/samples/standalone/dsl/http-server" target="_top">server
side code is available here</a> and <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/2.0.x/samples/standalone/dsl/http-client" target="_top">the
client code here</a>.</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>In this case, the producer owns the contracts. Physically, all the contract are
in the producer&#8217;s repository.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_technical_note" href="#_technical_note"></a>2.4.1&nbsp;Technical note</h3></div></div></div><p>If using the <span class="strong"><strong>SNAPSHOT</strong></span> / <span class="strong"><strong>Milestone</strong></span> / <span class="strong"><strong>Release Candidate</strong></span> versions please add the
following section to your build:</p><p class="primary"><b>Maven.&nbsp;</b>
@@ -596,7 +596,7 @@ of an identifier or a timestamp, you need not hardcode a value. You want to allo
different ranges of values. To enable ranges of values, you can set regular expressions
matching those values for the consumer side. You can provide the body by means of either
a map notation or String with interpolations.
Consult the <a class="xref" href="">???</a> section for more information. We highly recommend using the map notation!</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>You must understand the map notation in order to set up contracts. Please read the
Consult the <a class="xref" href="multi_contract-dsl.html" title="8.&nbsp;Contract DSL">Chapter&nbsp;8, <i>Contract DSL</i></a> section for more information. We highly recommend using the map notation!</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>You must understand the map notation in order to set up contracts. Please read the
<a class="link" href="http://groovy-lang.org/json.html" target="_top">Groovy docs regarding JSON</a>.</p></td></tr></table></div><p>The previously shown contract is an agreement between two sides that:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">if an HTTP request is sent with all of</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">a <code class="literal">PUT</code> method on the <code class="literal">/fraudcheck</code> endpoint,</li><li class="listitem">a JSON body with a <code class="literal">client.id</code> that matches the regular expression <code class="literal">[0-9]{10}</code> and
<code class="literal">loanAmount</code> equal to <code class="literal">99999</code>,</li><li class="listitem">and a <code class="literal">Content-Type</code> header with a value of <code class="literal">application/vnd.fraud.v1+json</code>,</li></ul></div></li><li class="listitem"><p class="simpara">then an HTTP response is sent to the consumer that</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">has status <code class="literal">200</code>,</li><li class="listitem">contains a JSON body with the <code class="literal">fraudCheckStatus</code> field containing a value <code class="literal">FRAUD</code> and
the <code class="literal">rejectionReason</code> field having value <code class="literal">Amount too high</code>,</li><li class="listitem">and a <code class="literal">Content-Type</code> header with a value of <code class="literal">application/vnd.fraud.v1+json</code>.</li></ul></div></li></ul></div><p>Once you are ready to check the API in practice in the integration tests, you need to

View File

@@ -208,7 +208,7 @@ then:
noExceptionThrown()
bookWasDeleted()
<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><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_consumer_stub_generation" href="#_consumer_stub_generation"></a>5.4&nbsp;Consumer Stub Generation</h2></div></div></div><p>Unlike the HTTP part, in messaging, we need to publish the Groovy DSL inside the JAR with
a stub. Then it is parsed on the consumer side and proper stubbed routes are created.</p><p>For more information, see <a class="xref" href="">???</a> section.</p><p class="primary"><b>Maven.&nbsp;</b>
a stub. Then it is parsed on the consumer side and proper stubbed routes are created.</p><p>For more information, see <a class="xref" href="multi_stub-runner-for-messaging.html" title="7.&nbsp;Stub Runner for Messaging">Chapter&nbsp;7, <i>Stub Runner for Messaging</i></a> section.</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>

View File

@@ -545,7 +545,7 @@ goal. Example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>Under <a class="xref" href="multi__using_the_pluggable_architecture.html#scm-stub-downloader" title="10.6&nbsp;Using the SCM Stub Downloader">Section&nbsp;10.6, &#8220;Using the SCM Stub Downloader&#8221;</a> you can find all possible
configuration options that you can pass either via
the <code class="literal">&lt;configuration&gt;&lt;contractProperties&gt;</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&nbsp;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/master/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-
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&nbsp;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.0.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
...
@@ -616,7 +616,7 @@ requires including an order number followed by an underscore. This will work reg
2_showCart.groovy
3_logout.groovy</pre><p>Such a tree causes Spring Cloud Contract Verifier to generate WireMock&#8217;s scenario with a
name of <code class="literal">scenario1</code> and the three following steps:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">login marked as <code class="literal">Started</code> pointing to&#8230;&#8203;</li><li class="listitem">showCart marked as <code class="literal">Step1</code> pointing to&#8230;&#8203;</li><li class="listitem">logout marked as <code class="literal">Step2</code> which will close the scenario.</li></ol></div><p>More details about WireMock scenarios can be found at
<a class="link" href="http://wiremock.org/stateful-behaviour.html" target="_top">http://wiremock.org/stateful-behaviour.html</a></p><p>Spring Cloud Contract Verifier also generates tests with a guaranteed order of execution.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="docker-project" href="#docker-project"></a>4.6&nbsp;Docker Project</h2></div></div></div><p>We&#8217;re publishing a <code class="literal">springcloud/spring-cloud-contract</code> Docker image
<a class="link" href="http://wiremock.org/docs/stateful-behaviour/" target="_top">http://wiremock.org/docs/stateful-behaviour/</a></p><p>Spring Cloud Contract Verifier also generates tests with a guaranteed order of execution.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="docker-project" href="#docker-project"></a>4.6&nbsp;Docker Project</h2></div></div></div><p>We&#8217;re publishing a <code class="literal">springcloud/spring-cloud-contract</code> Docker image
that contains a project that will generate tests and execute them in <code class="literal">EXPLICIT</code> mode
against a running application.</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>The <code class="literal">EXPLICIT</code> mode means that the tests generated from contracts will send
real requests and not the mocked ones.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_short_intro_to_maven_jars_and_binary_storage" href="#_short_intro_to_maven_jars_and_binary_storage"></a>4.6.1&nbsp;Short intro to Maven, JARs and Binary storage</h3></div></div></div><p>Since the Docker image can be used by non JVM projects, it&#8217;s good to

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,293 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>7.&nbsp;Stub Runner for Messaging</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_stub_runner.html" title="6.&nbsp;Spring Cloud Contract Stub Runner"><link rel="next" href="multi_contract-dsl.html" title="8.&nbsp;Contract DSL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7.&nbsp;Stub Runner for Messaging</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_stub_runner.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_contract-dsl.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="stub-runner-for-messaging" href="#stub-runner-for-messaging"></a>7.&nbsp;Stub Runner for Messaging</h1></div></div></div><p>Stub Runner can run the published stubs in memory. It can integrate with the following
frameworks:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Spring Integration</li><li class="listitem">Spring Cloud Stream</li><li class="listitem">Spring AMQP</li></ul></div><p>It also provides entry points to integrate with any other solution on the market.</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>If you have multiple frameworks on the classpath Stub Runner will need to
define which one should be used. Let&#8217;s assume that you have both AMQP, Spring Cloud Stream and Spring Integration
on the classpath. Then you need to set <code class="literal">stubrunner.stream.enabled=false</code> and <code class="literal">stubrunner.integration.enabled=false</code>.
That way the only remaining framework is Spring AMQP.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_triggering" href="#_stub_triggering"></a>7.1&nbsp;Stub triggering</h2></div></div></div><p>To trigger a message, use the <code class="literal">StubTrigger</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.stubrunner;
<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;
<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">/**
* Triggers an event by a given label for a given {@code groupid:artifactid} notation. You can use only {@code artifactId} too.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/</strong>
<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">/**
* Triggers an event by a given label.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/</strong>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger(String labelName);
<strong class="hl-tag" style="color: blue">/**
* Triggers all possible events.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/</strong>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger();
<strong class="hl-tag" style="color: blue">/**
* Returns a mapping of ivy notation of a dependency to all the labels it has.
*
* Feature related to messaging.
*/</strong>
Map&lt;String, Collection&lt;String&gt;&gt; labels();
}</pre><p>For convenience, the <code class="literal">StubFinder</code> interface extends <code class="literal">StubTrigger</code>, so you only need one
or the other in your tests.</p><p><code class="literal">StubTrigger</code> gives you the following options to trigger a message:</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#trigger-label" title="7.1.1&nbsp;Trigger by Label">Section&nbsp;7.1.1, &#8220;Trigger by Label&#8221;</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#trigger-group-artifact-ids" title="7.1.2&nbsp;Trigger by Group and Artifact Ids">Section&nbsp;7.1.2, &#8220;Trigger by Group and Artifact Ids&#8221;</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#trigger-artifact-ids" title="7.1.3&nbsp;Trigger by Artifact Ids">Section&nbsp;7.1.3, &#8220;Trigger by Artifact Ids&#8221;</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#trigger-all-messages" title="7.1.4&nbsp;Trigger All Messages">Section&nbsp;7.1.4, &#8220;Trigger All Messages&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-label" href="#trigger-label"></a>7.1.1&nbsp;Trigger by Label</h3></div></div></div><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-group-artifact-ids" href="#trigger-group-artifact-ids"></a>7.1.2&nbsp;Trigger by Group and Artifact Ids</h3></div></div></div><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:streamService'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-artifact-ids" href="#trigger-artifact-ids"></a>7.1.3&nbsp;Trigger by Artifact Ids</h3></div></div></div><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'streamService'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-all-messages" href="#trigger-all-messages"></a>7.1.4&nbsp;Trigger All Messages</h3></div></div></div><pre class="programlisting">stubFinder.trigger()</pre></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.2&nbsp;Stub Runner Integration</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module gives you an easy way to
integrate with Spring Integration. For the provided artifacts, it automatically downloads
the stubs and registers the required routes.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project" href="#_adding_the_runner_to_the_project"></a>7.2.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Spring Integration and Spring Cloud Contract Stub Runner on the
classpath. Remember to annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_disabling_the_functionality" href="#_disabling_the_functionality"></a>7.2.2&nbsp;Disabling the functionality</h3></div></div></div><p>If you need to disable this functionality, set the
<code class="literal">stubrunner.integration.enabled=false</code> property.</p><p>Assume that you have the following Maven repository with deployed stubs for the
<code class="literal">integrationService</code> application:</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; io
&#9492;&#9472;&#9472; codearte
&#9492;&#9472;&#9472; accurest
&#9492;&#9472;&#9472; stubs
&#9492;&#9472;&#9472; integrationService
&#9500;&#9472;&#9472; <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; integrationService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; integrationService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; repository
&#9500;&#9472;&#9472; accurest
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookDeleted.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookReturned1.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; bookReturned2.groovy
&#9492;&#9472;&#9472; mappings</pre><p>Consider the following contracts (numbered <span class="strong"><strong>1</strong></span>):</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>
input {
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>)
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'output'</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">'{ "bookName" : "foo" }'</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">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
}
}
}</pre><p>Now consider <span class="strong"><strong>2</strong></span>:</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_2'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'input'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>)
}
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'output'</span>)
body([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
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>and the following Spring Integration Route:</p><pre class="programlisting"><span class="hl-directive" style="color: maroon">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;beans: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>
<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">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- REQUIRED FOR TESTING --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;bridge</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">input-channel</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"output"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">output-channel</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"outputTest"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;channel</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"outputTest"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;queue/&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/channel&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/beans:beans&gt;</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#integration-scenario-1" title="Scenario 1 (no input message)">the section called &#8220;Scenario 1 (no input message)&#8221;</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#integration-scenario-2" title="Scenario 2 (output triggered by input)">the section called &#8220;Scenario 2 (output triggered by input)&#8221;</a></li><li class="listitem"><a class="xref" href="multi_stub-runner-for-messaging.html#integration-scenario-3" title="Scenario 3 (input with no output)">the section called &#8220;Scenario 3 (input with no output)&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="integration-scenario-1" href="#integration-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">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>To listen to the output of the message sent to <code class="literal">output</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'outputTest'</span>)</pre><p>The received message would pass the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.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="integration-scenario-2" href="#integration-scenario-2"></a>Scenario 2 (output triggered by input)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">output</code>
destination:</p><pre class="programlisting">messaging.send(<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>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'input'</span>)</pre><p>To listen to the output of the message sent to <code class="literal">output</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'outputTest'</span>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.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="integration-scenario-3" href="#integration-scenario-3"></a>Scenario 3 (input with no output)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">input</code> destination:</p><pre class="programlisting">messaging.send(<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>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete'</span>)</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_stream" href="#_stub_runner_stream"></a>7.3&nbsp;Stub Runner Stream</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module gives you an easy way to
integrate with Spring Stream. For the provided artifacts, it automatically downloads the
stubs and registers the required routes.</p><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>If Stub Runner&#8217;s integration with Stream the <code class="literal">messageFrom</code> or <code class="literal">sentTo</code> Strings
are resolved first as a <code class="literal">destination</code> of a channel and no such <code class="literal">destination</code> exists, the
destination is resolved as a channel name.</p></td></tr></table></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>If you want to use Spring Cloud Stream remember, to add a dependency on
<code class="literal">org.springframework.cloud:spring-cloud-stream-test-support</code>.</p></td></tr></table></div><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-stream-test-support<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-stream-test-support"</span></pre><p class="secondary">
</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project_2" href="#_adding_the_runner_to_the_project_2"></a>7.3.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Spring Cloud Stream and Spring Cloud Contract Stub Runner on the
classpath. Remember to annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_disabling_the_functionality_2" href="#_disabling_the_functionality_2"></a>7.3.2&nbsp;Disabling the functionality</h3></div></div></div><p>If you need to disable this functionality, set the <code class="literal">stubrunner.stream.enabled=false</code>
property.</p><p>Assume that you have the following Maven repository with a deployed stubs for the
<code class="literal">streamService</code> application:</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; io
&#9492;&#9472;&#9472; codearte
&#9492;&#9472;&#9472; accurest
&#9492;&#9472;&#9472; stubs
&#9492;&#9472;&#9472; streamService
&#9500;&#9472;&#9472; <span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; streamService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT.pom
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; streamService-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; repository
&#9500;&#9472;&#9472; accurest
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookDeleted.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookReturned1.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; bookReturned2.groovy
&#9492;&#9472;&#9472; mappings</pre><p>Consider the following contracts (numbered <span class="strong"><strong>1</strong></span>):</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>
input { triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>) }
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</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">'{ "bookName" : "foo" }'</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">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>) }
}
}</pre><p>Now consider <span class="strong"><strong>2</strong></span>:</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_2'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookStorage'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders { header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>) }
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)
body([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
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.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>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> stream</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> bindings</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> output</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> destination</span>: returnBook
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> input</span>:
<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">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 &#8220;Scenario 1 (no input message)&#8221;</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 &#8220;Scenario 2 (output triggered by input)&#8221;</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 &#8220;Scenario 3 (input with no output)&#8221;</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
<code class="literal">returnBook</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.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="stream-scenario-2" href="#stream-scenario-2"></a>Scenario 2 (output triggered by input)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">bookStorage</code>
<code class="literal">destination</code>:</p><pre class="programlisting">messaging.send(<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>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookStorage'</span>)</pre><p>To listen to the output of the message sent to <code class="literal">returnBook</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.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="stream-scenario-3" href="#stream-scenario-3"></a>Scenario 3 (input with no output)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">output</code>
destination:</p><pre class="programlisting">messaging.send(<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>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete'</span>)</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_spring_amqp" href="#_stub_runner_spring_amqp"></a>7.4&nbsp;Stub Runner Spring AMQP</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module provides an easy way to
integrate with Spring AMQP&#8217;s Rabbit Template. For the provided artifacts, it
automatically downloads the stubs and registers the required routes.</p><p>The integration tries to work standalone (that is, without interaction with a running
RabbitMQ message broker). It expects a <code class="literal">RabbitTemplate</code> on the application context and
uses it as a spring boot test named <code class="literal">@SpyBean</code>. As a result, it can use the mockito spy
functionality to verify and inspect messages sent by the application.</p><p>On the message consumer side, the stub runner considers all <code class="literal">@RabbitListener</code> annotated
endpoints and all <code class="literal">SimpleMessageListenerContainer</code> objects on the application context.</p><p>As messages are usually sent to exchanges in AMQP, the message contract contains the
exchange name as the destination. Message listeners on the other side are bound to
queues. Bindings connect an exchange to a queue. If message contracts are triggered, the
Spring AMQP stub runner integration looks for bindings on the application context that
match this exchange. Then it collects the queues from the Spring exchanges and tries to
find message listeners bound to these queues. The message is triggered for all matching
message listeners.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project_3" href="#_adding_the_runner_to_the_project_3"></a>7.4.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Spring AMQP and Spring Cloud Contract Stub Runner on the classpath and
set the property <code class="literal">stubrunner.amqp.enabled=true</code>. Remember to annotate your test class
with <code class="literal">@AutoConfigureStubRunner</code>.</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>If you already have Stream and Integration on the classpath, you need
to disable them explicitly by setting the <code class="literal">stubrunner.stream.enabled=false</code> and
<code class="literal">stubrunner.integration.enabled=false</code> properties.</p></td></tr></table></div><p>Assume that you have the following Maven repository with a deployed stubs for the
<code class="literal">spring-cloud-contract-amqp-test</code> application.</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; com
&#9492;&#9472;&#9472; example
&#9492;&#9472;&#9472; spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>
&#9500;&#9472;&#9472; <span class="hl-number">0.4</span>.<span class="hl-number">0</span>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; 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
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; 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
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume that the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; contracts
&#9492;&#9472;&#9472; shouldProduceValidPersonData.groovy</pre><p>Consider the following contract:</p><pre class="programlisting">Contract.make {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Human readable description</span>
description <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Should produce valid person data'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Label by means of which the output message can be triggered</span>
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contract-test.person.created.event'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// input to the contract</span>
input {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the contract will be triggered by a method</span>
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'createPerson()'</span>)
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// output message of the contract</span>
outputMessage {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// destination to which the output message will be sent</span>
sentTo <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contract-test.exchange'</span>
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contentType'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'__TypeId__'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person'</span>)
}
<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>))),
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"> 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
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>
<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>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test.queue"</span>);
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(value = "test.queue"),
exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))</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> 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
<code class="literal">MessageListener</code> associated with the matching <code class="literal">SimpleMessageListenerContainer</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_spring_amqp_test_configuration" href="#_spring_amqp_test_configuration"></a>Spring AMQP Test Configuration</h4></div></div></div><p>In order to avoid Spring AMQP trying to connect to a running broker during our tests
configure a mock <code class="literal">ConnectionFactory</code>.</p><p>To disable the mocked ConnectionFactory, set the following property:
<code class="literal">stubrunner.amqp.mockConnection=false</code></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"> amqp</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> mockConnection</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span></pre></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_stub_runner.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_contract-dsl.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6.&nbsp;Spring Cloud Contract Stub Runner&nbsp;</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">&nbsp;8.&nbsp;Contract DSL</td></tr></table></div></body></html>

File diff suppressed because one or more lines are too long

View File

@@ -53,7 +53,7 @@ Spring Cloud Contract Verifier.</simpara>
<informalfigure>
<mediaobject>
<imageobject>
<imagedata fileref="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/Deps.png"/>
<imagedata fileref="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.0.x/docs/src/main/asciidoc/images/Deps.png"/>
</imageobject>
<textobject><phrase>Microservices Architecture</phrase></textobject>
</mediaobject>
@@ -128,7 +128,7 @@ are those that your application directly uses.</simpara>
<informalfigure>
<mediaobject>
<imageobject>
<imagedata fileref="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/Stubs2.png"/>
<imagedata fileref="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.0.x/docs/src/main/asciidoc/images/Stubs2.png"/>
</imageobject>
<textobject><phrase>Stubbed Services</phrase></textobject>
</mediaobject>
@@ -707,8 +707,8 @@ we mark the client as a fraud.</simpara>
Issuance has an artifact-id of <literal>http-client</literal>, and both have a <literal>group-id</literal> of <literal>com.example</literal>.</simpara>
<simpara>Social remark - both client and server development teams need to communicate directly and
discuss changes while going through the process. CDC is all about communication.</simpara>
<simpara>The <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/dsl/http-server">server
side code is available here</link> and <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/dsl/http-client">the
<simpara>The <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/2.0.x/samples/standalone/dsl/http-server">server
side code is available here</link> and <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/2.0.x/samples/standalone/dsl/http-client">the
client code here</link>.</simpara>
<tip>
<simpara>In this case, the producer owns the contracts. Physically, all the contract are
@@ -994,7 +994,7 @@ of an identifier or a timestamp, you need not hardcode a value. You want to allo
different ranges of values. To enable ranges of values, you can set regular expressions
matching those values for the consumer side. You can provide the body by means of either
a map notation or String with interpolations.
Consult the <xref linkend="contract_dsl"/> section for more information. We highly recommend using the map notation!</simpara>
Consult the <xref linkend="contract-dsl"/> section for more information. We highly recommend using the map notation!</simpara>
<tip>
<simpara>You must understand the map notation in order to set up contracts. Please read the
<link xl:href="http://groovy-lang.org/json.html">Groovy docs regarding JSON</link>.</simpara>
@@ -1513,7 +1513,7 @@ consumer will you break with your local changes.</simpara>
<title>Repo structure</title>
<simpara>Let&#8217;s assume that we have a producer with coordinates <literal>com.example:server</literal> and 3 consumers: <literal>client1</literal>,
<literal>client2</literal>, <literal>client3</literal>. Then in the repository with common contracts you would have the following setup
(which you can checkout <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/contracts">here</link>):</simpara>
(which you can checkout <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/2.0.x/samples/standalone/contracts">here</link>):</simpara>
<programlisting language="bash" linenumbering="unnumbered">├── com
│   └── example
│   └── server
@@ -1550,14 +1550,14 @@ one to one to the contents of the repo.</simpara>
&lt;parent&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
&lt;version&gt;2.0.3.RELEASE&lt;/version&gt;
&lt;version&gt;2.0.4.RELEASE&lt;/version&gt;
&lt;relativePath /&gt;
&lt;/parent&gt;
&lt;properties&gt;
&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
&lt;java.version&gt;1.8&lt;/java.version&gt;
&lt;spring-cloud-contract.version&gt;2.1.0.BUILD-SNAPSHOT&lt;/spring-cloud-contract.version&gt;
&lt;spring-cloud-contract.version&gt;2.0.2.BUILD-SNAPSHOT&lt;/spring-cloud-contract.version&gt;
&lt;spring-cloud-release.version&gt;Finchley.BUILD-SNAPSHOT&lt;/spring-cloud-release.version&gt;
&lt;excludeBuildFolders&gt;true&lt;/excludeBuildFolders&gt;
&lt;/properties&gt;
@@ -1940,7 +1940,7 @@ Artifactory or Nexus. Starting from Spring Cloud Contract version 2.0.0 we provi
mechanisms to store contracts and stubs in a SCM repository. Currently the
only supported SCM is Git.</simpara>
<simpara>The repository would have to the following setup
(which you can checkout <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/contracts_git/">here</link>):</simpara>
(which you can checkout <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/contracts_git/">here</link>):</simpara>
<screen>.
└── META-INF
└── com.example
@@ -2153,7 +2153,7 @@ is not met.</simpara>
<title>Pact Consumer</title>
<simpara>The consumer uses Pact framework to generate Pact files. The
Pact files are sent to the Pact Broker. An example of such
setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/consumer_pact">here</link>.</simpara>
setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_pact">here</link>.</simpara>
</section>
<section xml:id="_producer_3">
<title>Producer</title>
@@ -2161,7 +2161,7 @@ setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring
same mechanism we use for external contracts. We route Spring Cloud Contract
to use the Pact implementation via the URL that contains
the <literal>pact://</literal> protocol. It&#8217;s enough to pass the URL to the
Pact Broker. An example of such setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/producer_pact">here</link>.</simpara>
Pact Broker. An example of such setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_pact">here</link>.</simpara>
<formalpara>
<title>Maven</title>
<para>
@@ -2248,7 +2248,7 @@ contracts {
(for every single consumer define the expectations) but you&#8217;d prefer
to do Producer Contracts (the producer provides the contracts and
publishes stubs), it&#8217;s enough to use Spring Cloud Contract with
Stub Runner option. An example of such setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/consumer_pact_stubrunner">here</link>.</simpara>
Stub Runner option. An example of such setup can be found <link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_pact_stubrunner">here</link>.</simpara>
<simpara>First, remember to add Stub Runner and Spring Cloud Contract Pact module
as test dependencies.</simpara>
<formalpara>
@@ -3304,7 +3304,7 @@ or an environment variable.</simpara>
<informalfigure>
<mediaobject>
<imageobject>
<imagedata fileref="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/sts_exception.png"/>
<imagedata fileref="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/2.0.x/docs/src/main/asciidoc/images/sts_exception.png"/>
</imageobject>
<textobject><phrase>STS Exception</phrase></textobject>
</mediaobject>
@@ -3440,7 +3440,7 @@ name of <literal>scenario1</literal> and the three following steps:</simpara>
</listitem>
</orderedlist>
<simpara>More details about WireMock scenarios can be found at
<link xl:href="http://wiremock.org/stateful-behaviour.html">http://wiremock.org/stateful-behaviour.html</link></simpara>
<link xl:href="http://wiremock.org/docs/stateful-behaviour/">http://wiremock.org/docs/stateful-behaviour/</link></simpara>
<simpara>Spring Cloud Contract Verifier also generates tests with a guaranteed order of execution.</simpara>
</section>
<section xml:id="docker-project">
@@ -5320,7 +5320,7 @@ the volume of your local m2 <literal>-v "${HOME}/.m2/:/root/.m2:ro"</literal></s
</section>
</section>
</chapter>
<chapter xml:id="_stub_runner_for_messaging">
<chapter xml:id="stub-runner-for-messaging">
<title>Stub Runner for Messaging</title>
<simpara>Stub Runner can run the published stubs in memory. It can integrate with the following
frameworks:</simpara>
@@ -5537,7 +5537,7 @@ follows:</simpara>
assertJsons(receivedMessage.payload)
receivedMessage.headers.get('BOOK-NAME') == 'foo'</programlisting>
</section>
<section xml:id="integration-scenario-1">
<section xml:id="integration-scenario-2">
<title>Scenario 2 (output triggered by input)</title>
<simpara>Since the route is set for you, you can send a message to the <literal>output</literal>
destination:</simpara>
@@ -5836,7 +5836,7 @@ configure a mock <literal>ConnectionFactory</literal>.</simpara>
</section>
</section>
</chapter>
<chapter xml:id="_contract_dsl">
<chapter xml:id="contract-dsl">
<title>Contract DSL</title>
<simpara>Spring Cloud Contract supports out of the box 2 types of DSL. One written in
<literal>Groovy</literal> and one written in <literal>YAML</literal>.</simpara>