Sync docs from master to gh-pages
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>8. Contract DSL</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__stub_runner_for_messaging.html" title="7. Stub Runner for Messaging"><link rel="next" href="multi__customization.html" title="9. Customization"></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">8. Contract DSL</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__stub_runner_for_messaging.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__customization.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_contract_dsl" href="#_contract_dsl"></a>8. Contract DSL</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>Remember that, inside the contract file, you have to provide the fully
|
||||
<title>8. Contract DSL</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__stub_runner_for_messaging.html" title="7. Stub Runner for Messaging"><link rel="next" href="multi__customization.html" title="9. Customization"></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">8. Contract DSL</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__stub_runner_for_messaging.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__customization.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_contract_dsl" href="#_contract_dsl"></a>8. Contract DSL</h1></div></div></div><p>Spring Cloud Contract supports out of the box 2 types of DSL. One written in
|
||||
<code class="literal">Groovy</code> and one written in <code class="literal">YAML</code>.</p><p>If you decide to write the contract in Groovy, do not be alarmed if you have not used Groovy
|
||||
before. Knowledge of the language is not really needed, as the Contract DSL uses only a
|
||||
tiny subset of it (only literals, method calls and closures). Also, the DSL is statically
|
||||
typed, to make it programmer-readable without any knowledge of the DSL itself.</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>Remember that, inside the Groovy contract file, you have to provide the fully
|
||||
qualified name to the <code class="literal">Contract</code> class and <code class="literal">make</code> static imports, such as
|
||||
<code class="literal">org.springframework.cloud.spec.Contract.make { …​ }</code>. You can also provide an import to
|
||||
the <code class="literal">Contract</code> class: <code class="literal">import org.springframework.cloud.spec.Contract</code> and then call
|
||||
<code class="literal">Contract.make { …​ }</code>.</p></td></tr></table></div><p>Contract DSL is written in Groovy, but do not be alarmed if you have not used Groovy
|
||||
before. Knowledge of the language is not really needed, as the Contract DSL uses only a
|
||||
tiny subset of it (only literals, method calls and closures). Also, the DSL is statically
|
||||
typed, to make it programmer-readable without any knowledge of the DSL itself.</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>Spring Cloud Contract supports defining multiple contracts in a single file.</p></td></tr></table></div><p>The Contract is present in the <code class="literal">spring-cloud-contract-spec</code> module of the
|
||||
<a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/spring-cloud-contract-verifier" target="_top">Spring
|
||||
Cloud Contract Verifier repository</a>.</p><p>The following is a complete example of a contract definition:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
<code class="literal">Contract.make { …​ }</code>.</p></td></tr></table></div><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>Spring Cloud Contract supports defining multiple contracts in a single file.</p></td></tr></table></div><p>The following is a complete example of a Groovy contract definition:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'PUT'</span>
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/api/12'</span>
|
||||
@@ -50,16 +49,60 @@ Cloud Contract Verifier repository</a>.</p><p>The following is a complete exampl
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
}
|
||||
}</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 preceding example does not contain all the features of the DSL appear. The
|
||||
remainder of this section describes the other features.</p></td></tr></table></div><p>You can compile Contracts to WireMock stubs mapping using standalone maven command:
|
||||
<code class="literal">mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:convert</code></p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_limitations_2" href="#_limitations_2"></a>8.1 Limitations</h2></div></div></div><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>Spring Cloud Contract Verifier does not properly support XML. Please use JSON or
|
||||
}</pre><p>The following is a complete example of a YAML contract definition:</p><pre class="programlisting">description: Some description
|
||||
name: some name
|
||||
priority: 8
|
||||
ignored: true
|
||||
request:
|
||||
url: /foo
|
||||
queryParameters:
|
||||
a: b
|
||||
b: c
|
||||
method: PUT
|
||||
headers:
|
||||
foo: bar
|
||||
fooReq: baz
|
||||
body:
|
||||
foo: bar
|
||||
matchers:
|
||||
body:
|
||||
- path: $.foo
|
||||
type: by_regex
|
||||
value: bar
|
||||
headers:
|
||||
- key: foo
|
||||
regex: bar
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
foo2: bar
|
||||
foo3: foo33
|
||||
fooRes: baz
|
||||
body:
|
||||
foo2: bar
|
||||
foo3: baz
|
||||
matchers:
|
||||
body:
|
||||
- path: $.foo2
|
||||
type: by_regex
|
||||
value: bar
|
||||
- path: $.foo3
|
||||
type: by_command
|
||||
value: executeMe($it)
|
||||
headers:
|
||||
- key: foo2
|
||||
regex: bar
|
||||
- key: foo3
|
||||
command: andMeToo($it)</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>You can compile contracts to stubs mapping using standalone maven command:
|
||||
<code class="literal">mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:convert</code></p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_limitations_2" href="#_limitations_2"></a>8.1 Limitations</h2></div></div></div><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>Spring Cloud Contract Verifier does not properly support XML. Please use JSON or
|
||||
help us implement this feature.</p></td></tr></table></div><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>The support for verifying the size of JSON arrays is experimental. If you want
|
||||
to turn it on, please set the value of the following system property to <code class="literal">true</code>:
|
||||
<code class="literal">spring.cloud.contract.verifier.assert.size</code>. By default, this feature is set to <code class="literal">false</code>.
|
||||
You can also provide the <code class="literal">assertJsonSize</code> property in the plugin configuration.</p></td></tr></table></div><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>Because JSON structure can have any form, it can be impossible to parse it
|
||||
properly when using the <code class="literal">value(consumer(…​), producer(…​))</code> notation in <code class="literal">GString</code>. That
|
||||
properly when using the Groovy DSL and the <code class="literal">value(consumer(…​), producer(…​))</code> notation in <code class="literal">GString</code>. That
|
||||
is why you should use the Groovy Map notation.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_common_top_level_elements" href="#_common_top_level_elements"></a>8.2 Common Top-Level elements</h2></div></div></div><p>The following sections describe the most common top-level elements:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-description" title="8.2.1 Description">Section 8.2.1, “Description”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-name" title="8.2.2 Name">Section 8.2.2, “Name”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-ignoring-contracts" title="8.2.3 Ignoring Contracts">Section 8.2.3, “Ignoring Contracts”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-passing-values-from-files" title="8.2.4 Passing Values from Files">Section 8.2.4, “Passing Values from Files”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-http-top-level-elements" title="8.2.5 HTTP Top-Level Elements">Section 8.2.5, “HTTP Top-Level Elements”</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-description" href="#contract-dsl-description"></a>8.2.1 Description</h3></div></div></div><p>You can add a <code class="literal">description</code> to your contract. The description is arbitrary text. The
|
||||
following code shows an example:</p><pre class="programlisting"> org.springframework.cloud.contract.spec.Contract.make {
|
||||
following code shows an example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting"> org.springframework.cloud.contract.spec.Contract.make {
|
||||
description(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span>given:
|
||||
An input
|
||||
@@ -68,23 +111,81 @@ when:
|
||||
then:
|
||||
Output
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">')
|
||||
</span> }</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-name" href="#contract-dsl-name"></a>8.2.2 Name</h3></div></div></div><p>You can provide a name for your contract. Assume that you provided the following name:
|
||||
</span> }</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">description: Some description
|
||||
name: some name
|
||||
priority: 8
|
||||
ignored: true
|
||||
request:
|
||||
url: /foo
|
||||
queryParameters:
|
||||
a: b
|
||||
b: c
|
||||
method: PUT
|
||||
headers:
|
||||
foo: bar
|
||||
fooReq: baz
|
||||
body:
|
||||
foo: bar
|
||||
matchers:
|
||||
body:
|
||||
- path: $.foo
|
||||
type: by_regex
|
||||
value: bar
|
||||
headers:
|
||||
- key: foo
|
||||
regex: bar
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
foo2: bar
|
||||
foo3: foo33
|
||||
fooRes: baz
|
||||
body:
|
||||
foo2: bar
|
||||
foo3: baz
|
||||
matchers:
|
||||
body:
|
||||
- path: $.foo2
|
||||
type: by_regex
|
||||
value: bar
|
||||
- path: $.foo3
|
||||
type: by_command
|
||||
value: executeMe($it)
|
||||
headers:
|
||||
- key: foo2
|
||||
regex: bar
|
||||
- key: foo3
|
||||
command: andMeToo($it)</pre><p>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-name" href="#contract-dsl-name"></a>8.2.2 Name</h3></div></div></div><p>You can provide a name for your contract. Assume that you provided the following name:
|
||||
<code class="literal">should register a user</code>. If you do so, the name of the autogenerated test is
|
||||
<code class="literal">validate_should_register_a_user</code>. Also, the name of the stub in a WireMock stub is
|
||||
<code class="literal">should_register_a_user.json</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>You must ensure that the name does not contain any characters that make the
|
||||
generated test not compile. Also, remember that, if you provide the same name for
|
||||
multiple contracts, your autogenerated tests fail to compile and your generated stubs
|
||||
override each other.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-ignoring-contracts" href="#contract-dsl-ignoring-contracts"></a>8.2.3 Ignoring Contracts</h3></div></div></div><p>If you want to ignore a contract, you can either set a value of ignored contracts in the
|
||||
plugin configuration or set the <code class="literal">ignored</code> property on the contract itself:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
override each other.</p></td></tr></table></div><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"some_special_name"</span>)
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">name: some name</pre><p>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-ignoring-contracts" href="#contract-dsl-ignoring-contracts"></a>8.2.3 Ignoring Contracts</h3></div></div></div><p>If you want to ignore a contract, you can either set a value of ignored contracts in the
|
||||
plugin configuration or set the <code class="literal">ignored</code> property on the contract itself:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
ignored()
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-passing-values-from-files" href="#contract-dsl-passing-values-from-files"></a>8.2.4 Passing Values from Files</h3></div></div></div><p>Starting with version <code class="literal">1.2.0</code>, you can pass values from files. Assume that you have the
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">ignored: true</pre><p>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-passing-values-from-files" href="#contract-dsl-passing-values-from-files"></a>8.2.4 Passing Values from Files</h3></div></div></div><p>Starting with version <code class="literal">1.2.0</code>, you can pass values from files. Assume that you have the
|
||||
following resources in our project.</p><pre class="programlisting">└── src
|
||||
└── <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>
|
||||
└── resources
|
||||
└── contracts
|
||||
├── readFromFile.groovy
|
||||
├── request.json
|
||||
└── response.json</pre><p>Further assume that your contract is as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
└── response.json</pre><p>Further assume that your contract is as follows:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
Contract.make {
|
||||
request {
|
||||
@@ -102,11 +203,20 @@ Contract.make {
|
||||
contentType(textPlain())
|
||||
}
|
||||
}
|
||||
}</pre><p>Further assume that the JSON files is as follows:</p><p><span class="strong"><strong>request.json</strong></span></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"REQUEST"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p><span class="strong"><strong>response.json</strong></span></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RESPONSE"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>When test or stub generation takes place, the contents of the file is passed to the body
|
||||
of a request or a response. That works because of the <code class="literal">file(…​)</code> method. The argument of
|
||||
that method needs to be a file with location relative to the folder in which the contract
|
||||
lays.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-http-top-level-elements" href="#contract-dsl-http-top-level-elements"></a>8.2.5 HTTP Top-Level Elements</h3></div></div></div><p>The following methods can be called in the top-level closure of a contract definition.
|
||||
<code class="literal">request</code> and <code class="literal">response</code> are mandatory. <code class="literal">priority</code> is optional.</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
method: GET
|
||||
url: /foo
|
||||
bodyFromFile: request.json
|
||||
response:
|
||||
status: 200
|
||||
bodyFromFile: response.json</pre><p>
|
||||
</p><p>Further assume that the JSON files is as follows:</p><p><span class="strong"><strong>request.json</strong></span></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"REQUEST"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p><span class="strong"><strong>response.json</strong></span></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RESPONSE"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>When test or stub generation takes place, the contents of the file is passed to the body
|
||||
of a request or a response. The name of the file needs to be a file with location
|
||||
relative to the folder in which the contract lays.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-http-top-level-elements" href="#contract-dsl-http-top-level-elements"></a>8.2.5 HTTP Top-Level Elements</h3></div></div></div><p>The following methods can be called in the top-level closure of a contract definition.
|
||||
<code class="literal">request</code> and <code class="literal">response</code> are mandatory. <code class="literal">priority</code> is optional.</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Definition of HTTP request part of the contract</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (this can be a valid request or invalid depending</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// on type of contract being specified).</span>
|
||||
@@ -125,8 +235,18 @@ lays.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Contract priority, which can be used for overriding</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// contracts (1 is highest). Priority is optional.</span>
|
||||
priority <span class="hl-number">1</span>
|
||||
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_request" href="#_request"></a>8.3 Request</h2></div></div></div><p>The HTTP protocol requires only <span class="strong"><strong>method and address</strong></span> to be specified in a request. The
|
||||
same information is mandatory in request definition of the Contract.</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">priority: 8
|
||||
request:
|
||||
...
|
||||
response:
|
||||
...</pre><p>
|
||||
</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 want to make your contract have a <span class="strong"><strong>higher</strong></span> value of priority
|
||||
you need to pass a <span class="strong"><strong>lower</strong></span> number to the <code class="literal">priority</code> tag / method. E.g. <code class="literal">priority</code> with
|
||||
value <code class="literal">5</code> has <span class="strong"><strong>higher</strong></span> priority than <code class="literal">priority</code> with value <code class="literal">10</code>.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_request" href="#_request"></a>8.3 Request</h2></div></div></div><p>The HTTP protocol requires only <span class="strong"><strong>method and url</strong></span> to be specified in a request. The
|
||||
same information is mandatory in request definition of the Contract.</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// HTTP request method (GET/POST/PUT/DELETE).</span>
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
|
||||
@@ -138,8 +258,13 @@ same information is mandatory in request definition of the Contract.</p><pre cla
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
}</pre><p>It is possible to specify an absolute rather than relative <code class="literal">url</code>, but using <code class="literal">urlPath</code> is
|
||||
the recommended way, as doing so makes the tests <span class="strong"><strong>host-independent</strong></span>.</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">method: PUT
|
||||
url: /foo</pre><p>
|
||||
</p><p>It is possible to specify an absolute rather than relative <code class="literal">url</code>, but using <code class="literal">urlPath</code> is
|
||||
the recommended way, as doing so makes the tests <span class="strong"><strong>host-independent</strong></span>.</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
|
||||
|
||||
@@ -150,8 +275,13 @@ the recommended way, as doing so makes the tests <span class="strong"><strong>ho
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
}</pre><p><code class="literal">request</code> may contain <span class="strong"><strong>query parameters</strong></span>, which are specified in a closure nested in a
|
||||
call to <code class="literal">urlPath</code> or <code class="literal">url</code>.</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
method: PUT
|
||||
urlPath: /foo</pre><p>
|
||||
</p><p><code class="literal">request</code> may contain <span class="strong"><strong>query parameters</strong></span>.</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
|
||||
@@ -191,7 +321,50 @@ call to <code class="literal">urlPath</code> or <code class="literal">url</code>
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
}</pre><p><code class="literal">request</code> may contain additional <span class="strong"><strong>request headers</strong></span>, as shown in the following example:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
...
|
||||
queryParameters:
|
||||
a: b
|
||||
b: c
|
||||
headers:
|
||||
foo: bar
|
||||
fooReq: baz
|
||||
body:
|
||||
foo: bar
|
||||
matchers:
|
||||
body:
|
||||
- path: $.foo
|
||||
type: by_regex
|
||||
value: bar
|
||||
headers:
|
||||
- key: foo
|
||||
regex: bar
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
foo2: bar
|
||||
foo3: foo33
|
||||
fooRes: baz
|
||||
body:
|
||||
foo2: bar
|
||||
foo3: baz
|
||||
matchers:
|
||||
body:
|
||||
- path: $.foo2
|
||||
type: by_regex
|
||||
value: bar
|
||||
- path: $.foo3
|
||||
type: by_command
|
||||
value: executeMe($it)
|
||||
headers:
|
||||
- key: foo2
|
||||
regex: bar
|
||||
- key: foo3
|
||||
command: andMeToo($it)</pre><p>
|
||||
</p><p><code class="literal">request</code> may contain additional <span class="strong"><strong>request headers</strong></span>, as shown in the following example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
|
||||
@@ -208,7 +381,15 @@ call to <code class="literal">urlPath</code> or <code class="literal">url</code>
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
}</pre><p><code class="literal">request</code> may contain a <span class="strong"><strong>request body</strong></span>, as shown in the following example:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
...
|
||||
headers:
|
||||
foo: bar
|
||||
fooReq: baz</pre><p>
|
||||
</p><p><code class="literal">request</code> may contain a <span class="strong"><strong>request body</strong></span>:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
|
||||
@@ -220,8 +401,15 @@ call to <code class="literal">urlPath</code> or <code class="literal">url</code>
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
}</pre><p><code class="literal">request</code> may contain <span class="strong"><strong>multipart</strong></span> elements. To include multipart elements, call the
|
||||
<code class="literal">multipart()</code> method, as shown in the following example</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract contractDsl = org.springframework.cloud.contract.spec.Contract.make {
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
...
|
||||
body:
|
||||
foo: bar</pre><p>
|
||||
</p><p><code class="literal">request</code> may contain <span class="strong"><strong>multipart</strong></span> elements. To include multipart elements, use the
|
||||
<code class="literal">multipart</code> method/section, as shown in the following examples</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract contractDsl = org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PUT"</span>
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/multipart"</span>
|
||||
@@ -244,11 +432,49 @@ call to <code class="literal">urlPath</code> or <code class="literal">url</code>
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
}
|
||||
}</pre><p>In the preceding example, we define parameters in either of two ways:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Directly, by using the map notation, where the value can be a dynamic property (such as
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
method: PUT
|
||||
url: /multipart
|
||||
headers:
|
||||
Content-Type: multipart/form-data;boundary=AaB03x
|
||||
multipart:
|
||||
params:
|
||||
# key (parameter name), value (parameter value) pair
|
||||
formParameter: '"formParameterValue"'
|
||||
someBooleanParameter: true
|
||||
named:
|
||||
- paramName: file
|
||||
fileName: filename.csv
|
||||
fileContent: file content
|
||||
matchers:
|
||||
multipart:
|
||||
params:
|
||||
- key: formParameter
|
||||
regex: ".+"
|
||||
- key: someBooleanParameter
|
||||
predefined: any_boolean
|
||||
named:
|
||||
- paramName: file
|
||||
fileName:
|
||||
predefined: non_empty
|
||||
fileContent:
|
||||
predefined: non_empty
|
||||
response:
|
||||
status: 200</pre><p>
|
||||
</p><p>In the preceding example, we define parameters in either of two ways:</p><div class="itemizedlist"><p class="title"><b>Groovy DSL</b></p><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Directly, by using the map notation, where the value can be a dynamic property (such as
|
||||
<code class="literal">formParameter: $(consumer(…​), producer(…​))</code>).</li><li class="listitem">By using the <code class="literal">named(…​)</code> method that lets you set a named parameter. A named parameter
|
||||
can set a <code class="literal">name</code> and <code class="literal">content</code>. You can call it either via a method with two arguments,
|
||||
such as <code class="literal">named("fileName", "fileContent")</code>, or via a map notation, such as
|
||||
<code class="literal">named(name: "fileName", content: "fileContent")</code>.</li></ul></div><p>From this contract, the generated test is as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
<code class="literal">named(name: "fileName", content: "fileContent")</code>.</li></ul></div><div class="itemizedlist"><p class="title"><b>YAML</b></p><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The multipart parameters are set via <code class="literal">multipart.params</code> section</li><li class="listitem">The named parameters (the <code class="literal">fileName</code> and <code class="literal">fileContent</code> for a given parameter name)
|
||||
can be set via the <code class="literal">multipart.named</code> section. That section contains
|
||||
the <code class="literal">paramName</code> (name of the parameter), <code class="literal">fileName</code> (name of the file),
|
||||
<code class="literal">fileContent</code> (content of the file) fields</li><li class="listitem"><p class="simpara">The dynamic bits can be set via the <code class="literal">matchers.multipart</code> section</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">for parameters use the <code class="literal">params</code> section that can accept
|
||||
<code class="literal">regex</code> or a <code class="literal">predefined</code> regular expression</li><li class="listitem">for named params use the <code class="literal">named</code> section where first you
|
||||
define the parameter name via <code class="literal">paramName</code> and then you can pass the
|
||||
parametrization of either <code class="literal">fileName</code> or <code class="literal">fileContent</code> via
|
||||
<code class="literal">regex</code> or a <code class="literal">predefined</code> regular expression</li></ul></div></li></ul></div><p>From this contract, the generated test is as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"multipart/form-data;boundary=AaB03x"</span>)
|
||||
.param(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"formParameter"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"\"formParameterValue\""</span>)
|
||||
@@ -284,7 +510,8 @@ such as <code class="literal">named("fileName", "fileContent")</code>, or via a
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_response" href="#_response"></a>8.4 Response</h2></div></div></div><p>The response must contain an <span class="strong"><strong>HTTP status code</strong></span> and may contain other information. The
|
||||
following code shows an example:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
following code shows an example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
||||
}
|
||||
@@ -293,12 +520,18 @@ following code shows an example:</p><pre class="programlisting">org.springframew
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// in response to request specified above.</span>
|
||||
status <span class="hl-number">200</span>
|
||||
}
|
||||
}</pre><p>Besides status, the response may contain <span class="strong"><strong>headers</strong></span> and a <span class="strong"><strong>body</strong></span>, both of which are
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">response:
|
||||
...
|
||||
status: 200</pre><p>
|
||||
</p><p>Besides status, the response may contain <span class="strong"><strong>headers</strong></span> and a <span class="strong"><strong>body</strong></span>, both of which are
|
||||
specified the same way as in the request (see the previous paragraph).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_dynamic_properties" href="#_dynamic_properties"></a>8.5 Dynamic properties</h2></div></div></div><p>The contract can contain some dynamic properties: timestamps, IDs, and so on. You do not
|
||||
want to force the consumers to stub their clocks to always return the same value of time
|
||||
so that it gets matched by the stub. You can provide the dynamic parts in your contracts
|
||||
so that it gets matched by the stub.</p><p>For Groovy DSL you can provide the dynamic parts in your contracts
|
||||
in two ways: pass them directly in the body or set them in separate sections called
|
||||
<code class="literal">testMatchers</code> and <code class="literal">stubMatchers</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dynamic_properties_inside_the_body" href="#_dynamic_properties_inside_the_body"></a>8.5.1 Dynamic properties inside the body</h3></div></div></div><p>You can set the properties inside the body either with the <code class="literal">value</code> method or, if you use
|
||||
<code class="literal">testMatchers</code> and <code class="literal">stubMatchers</code>.</p><p>For YAML you can only use the <code class="literal">matchers</code> section.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dynamic_properties_inside_the_body" href="#_dynamic_properties_inside_the_body"></a>8.5.1 Dynamic properties inside the body</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL. Check out the
|
||||
<a class="xref" href="multi__contract_dsl.html#contract-matchers" title="8.5.7 Dynamic Properties in the Matchers Sections">Section 8.5.7, “Dynamic Properties in the Matchers Sections”</a> section for YAML examples of a similar feature.</p></td></tr></table></div><p>You can set the properties inside the body either with the <code class="literal">value</code> method or, if you use
|
||||
the Groovy map notation, with <code class="literal">$()</code>. The following example shows how to set dynamic
|
||||
properties with the value method:</p><pre class="programlisting">value(consumer(...), producer(...))
|
||||
value(c(...), p(...))
|
||||
@@ -307,7 +540,8 @@ value(client(...), server(...))</pre><p>The following example shows how to set d
|
||||
$(c(...), p(...))
|
||||
$(stub(...), test(...))
|
||||
$(client(...), server(...))</pre><p>Both approaches work equally well. <code class="literal">stub</code> and <code class="literal">client</code> methods are aliases over the <code class="literal">consumer</code>
|
||||
method. Subsequent sections take a closer look at what you can do with those values.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_regular_expressions" href="#_regular_expressions"></a>8.5.2 Regular expressions</h3></div></div></div><p>You can use regular expressions to write your requests in Contract DSL. Doing so is
|
||||
method. Subsequent sections take a closer look at what you can do with those values.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_regular_expressions" href="#_regular_expressions"></a>8.5.2 Regular expressions</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL. Check out the
|
||||
<a class="xref" href="multi__contract_dsl.html#contract-matchers" title="8.5.7 Dynamic Properties in the Matchers Sections">Section 8.5.7, “Dynamic Properties in the Matchers Sections”</a> section for YAML examples of a similar feature.</p></td></tr></table></div><p>You can use regular expressions to write your requests in Contract DSL. Doing so is
|
||||
particularly useful when you want to indicate that a given response should be provided
|
||||
for requests that follow a given pattern. Also, you can use regular expressions when you
|
||||
need to use patterns and not exact values both for your test and your server side tests.</p><p>The following example shows how to use regular expressions to write a request:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
@@ -453,7 +687,8 @@ Pattern nonBlank() {
|
||||
message: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]"</span>
|
||||
)
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_passing_optional_parameters" href="#_passing_optional_parameters"></a>8.5.3 Passing Optional Parameters</h3></div></div></div><p>It is possible to provide optional parameters in your contract. However, you can provide
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_passing_optional_parameters" href="#_passing_optional_parameters"></a>8.5.3 Passing Optional Parameters</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL. Check out the
|
||||
<a class="xref" href="multi__contract_dsl.html#contract-matchers" title="8.5.7 Dynamic Properties in the Matchers Sections">Section 8.5.7, “Dynamic Properties in the Matchers Sections”</a> section for YAML examples of a similar feature.</p></td></tr></table></div><p>It is possible to provide optional parameters in your contract. However, you can provide
|
||||
optional parameters only for the following:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="emphasis"><em>STUB</em></span> side of the Request</li><li class="listitem"><span class="emphasis"><em>TEST</em></span> side of the Response</li></ul></div><p>The following example shows how to provide optional parameters:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
priority <span class="hl-number">1</span>
|
||||
request {
|
||||
@@ -496,29 +731,30 @@ expression that must be present 0 or more times.</p><p>If you use Spock for, the
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"</span></pre><p>The following stub would also be generated:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span>{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/users/password"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"POST"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bodyPatterns"</span> : [ {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['email'] =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,6})?/)]"</span>
|
||||
}, {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['callback_url'] =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]"</span>
|
||||
} ],
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"equalTo"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
}
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/users/password"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"POST"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bodyPatterns"</span> : [ {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['email'] =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,6})?/)]"</span>
|
||||
}, {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['callback_url'] =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]"</span>
|
||||
} ],
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"equalTo"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
}
|
||||
}
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">404</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>code\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">123123</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>message\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>User not found by email == [not.existing<em><span class="hl-annotation" style="color: gray">@user.com]\\"}",</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">404</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>code\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">123123</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>message\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>User not found by email == [not.existing<em><span class="hl-annotation" style="color: gray">@user.com]\\"}",</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
}
|
||||
},
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"priority"</span> : <span class="hl-number">1</span>
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_executing_custom_methods_on_the_server_side" href="#_executing_custom_methods_on_the_server_side"></a>8.5.4 Executing Custom Methods on the Server Side</h3></div></div></div><p>You can define a method call that executes on the server side during the test. Such a
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_executing_custom_methods_on_the_server_side" href="#_executing_custom_methods_on_the_server_side"></a>8.5.4 Executing Custom Methods on the Server Side</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL. Check out the
|
||||
<a class="xref" href="multi__contract_dsl.html#contract-matchers" title="8.5.7 Dynamic Properties in the Matchers Sections">Section 8.5.7, “Dynamic Properties in the Matchers Sections”</a> section for YAML examples of a similar feature.</p></td></tr></table></div><p>You can define a method call that executes on the server side during the test. Such a
|
||||
method can be added to the class defined as "baseClassForTests" in the configuration. The
|
||||
following code shows an example of the contract portion of the test case:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
@@ -582,11 +818,17 @@ It should resemble the following code:</p><pre class="programlisting"><span xmln
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
|
||||
assertThat(response.statusCode()).isEqualTo(<span class="hl-number">200</span>);</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_referencing_the_request_from_the_response" href="#_referencing_the_request_from_the_response"></a>8.5.5 Referencing the Request from the Response</h3></div></div></div><p>The best situation is to provide fixed values, but sometimes you need to reference a
|
||||
request in your response. To do so, you can use the <code class="literal">fromRequest()</code> method, which lets
|
||||
request in your response.</p><p>If you’re writing contracts using Groovy DSL, you can use the <code class="literal">fromRequest()</code> method, which lets
|
||||
you reference a bunch of elements from the HTTP request. You can use the following
|
||||
options:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">fromRequest().url()</code>: Returns the request URL and query parameters.</li><li class="listitem"><code class="literal">fromRequest().query(String key)</code>: Returns the first query parameter with a given name.</li><li class="listitem"><code class="literal">fromRequest().query(String key, int index)</code>: Returns the nth query parameter with a
|
||||
given name.</li><li class="listitem"><code class="literal">fromRequest().path()</code>: Returns the full path.</li><li class="listitem"><code class="literal">fromRequest().path(int index)</code>: Returns the nth path element.</li><li class="listitem"><code class="literal">fromRequest().header(String key)</code>: Returns the first header with a given name.</li><li class="listitem"><code class="literal">fromRequest().header(String key, int index)</code>: Returns the nth header with a given name.</li><li class="listitem"><code class="literal">fromRequest().body()</code>: Returns the full request body.</li><li class="listitem"><code class="literal">fromRequest().body(String jsonPath)</code>: Returns the element from the request that
|
||||
matches the JSON Path.</li></ul></div><p>Consider the following contract:</p><pre class="programlisting">Contract contractDsl = Contract.make {
|
||||
matches the JSON Path.</li></ul></div><p>If you’re using the YAML contract definition you have to use the
|
||||
<a class="link" href="http://handlebarsjs.com/" target="_top">Handlebars</a> <code class="literal">{{{ }}}</code> notation with custom, Spring Cloud Contract
|
||||
functions to achieve this.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">{{{ request.url }}}</code>: Returns the request URL and query parameters.</li><li class="listitem"><code class="literal">{{{ request.query.key.[index] }}}</code>: Returns the nth query parameter with a given name.
|
||||
E.g. for key <code class="literal">foo</code>, first entry <code class="literal">{{{ request.query.foo.[0] }}}</code></li><li class="listitem"><code class="literal">{{{ request.path }}}</code>: Returns the full path.</li><li class="listitem"><code class="literal">{{{ request.path.[index] }}}</code>: Returns the nth path element. E.g.
|
||||
for first entry <code class="literal">`</code>{{{ request.path.[0] }}}</li><li class="listitem"><code class="literal">{{{ request.headers.key }}}</code>: Returns the first header with a given name.</li><li class="listitem"><code class="literal">{{{ request.headers.key.[index] }}}</code>: Returns the nth header with a given name.</li><li class="listitem"><code class="literal">{{{ request.body }}}</code>: Returns the full request body.</li><li class="listitem"><code class="literal">{{{ jsonpath this 'your.json.path' }}}</code>: Returns the element from the request that
|
||||
matches the JSON Path. E.g. for json path <code class="literal">$.foo</code> - <code class="literal">{{{ jsonpath this '$.foo' }}}</code></li></ul></div><p>Consider the following contract:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
|
||||
url(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/api/v1/xxxx'</span>) {
|
||||
@@ -620,7 +862,39 @@ matches the JSON Path.</li></ul></div><p>Consider the following contract:</p><pr
|
||||
responseBaz2: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Bla bla ${fromRequest().body('$.foo')} bla bla"</span>
|
||||
)
|
||||
}
|
||||
}</pre><p>Running a JUnit test generation leads to a test that resembles the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
method: GET
|
||||
url: /api/v1/xxxx
|
||||
queryParameters:
|
||||
foo:
|
||||
- bar
|
||||
- bar2
|
||||
headers:
|
||||
Authorization:
|
||||
- secret
|
||||
- secret2
|
||||
body:
|
||||
foo: bar
|
||||
baz: 5
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
Authorization: "foo {{{ request.headers.Authorization.0 }}} bar"
|
||||
body:
|
||||
url: "{{{ request.url }}}"
|
||||
path: "{{{ request.path }}}"
|
||||
pathIndex: "{{{ request.path.1 }}}"
|
||||
param: "{{{ request.query.foo }}}"
|
||||
paramIndex: "{{{ request.query.foo.1 }}}"
|
||||
authorization: "{{{ request.headers.Authorization.0 }}}"
|
||||
authorization2: "{{{ request.headers.Authorization.1 }}"
|
||||
fullBody: "{{{ request.body }}}"
|
||||
responseFoo: "{{{ jsonpath this '$.foo' }}}"
|
||||
responseBaz: "{{{ jsonpath this '$.baz' }}}"
|
||||
responseBaz2: "Bla bla {{{ jsonpath this '$.foo' }}} bla bla"</pre><p>
|
||||
</p><p>Running a JUnit test generation leads to a test that resembles the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Authorization"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secret"</span>)
|
||||
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Authorization"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secret2"</span>)
|
||||
@@ -723,12 +997,12 @@ org.springframework.cloud.contract.stubrunner.provider.wiremock.TestWireMockExte
|
||||
}
|
||||
}</pre><p>
|
||||
</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>Remember to override the <code class="literal">applyGlobally()</code> method and set it to <code class="literal">false</code> if you
|
||||
want the transformation to be applied only for a mapping that explicitly requires it.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dynamic_properties_in_the_matchers_sections" href="#_dynamic_properties_in_the_matchers_sections"></a>8.5.7 Dynamic Properties in the Matchers Sections</h3></div></div></div><p>If you work with <a class="link" href="https://docs.pact.io/" target="_top">Pact</a>, the following discussion may seem familiar.
|
||||
want the transformation to be applied only for a mapping that explicitly requires it.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-matchers" href="#contract-matchers"></a>8.5.7 Dynamic Properties in the Matchers Sections</h3></div></div></div><p>If you work with <a class="link" href="https://docs.pact.io/" target="_top">Pact</a>, the following discussion may seem familiar.
|
||||
Quite a few users are used to having a separation between the body and setting the
|
||||
dynamic parts of a contract.</p><p>You can use two separate sections:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">stubMatchers</code>, which lets you define the dynamic values that should end up in a stub.
|
||||
You can set it in the <code class="literal">request</code> or <code class="literal">inputMessage</code> part of your contract.</li><li class="listitem"><code class="literal">testMatchers</code>, which is present in the <code class="literal">response</code> or <code class="literal">outputMessage</code> side of the
|
||||
contract.</li></ul></div><p>Currently, Spring Cloud Contract Verifier supports only JSON Path-based matchers with the
|
||||
following matching possibilities:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">For <code class="literal">stubMatchers</code>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><code class="literal">byEquality()</code>: The value taken from the response via the provided JSON Path must be
|
||||
following matching possibilities:</p><div class="itemizedlist"><p class="title"><b>Groovy DSL</b></p><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">For <code class="literal">stubMatchers</code>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><code class="literal">byEquality()</code>: The value taken from the response via the provided JSON Path must be
|
||||
equal to the value provided in the contract.</li><li class="listitem"><code class="literal">byRegex(…​)</code>: The value taken from the response via the provided JSON Path must
|
||||
match the regex.</li><li class="listitem"><code class="literal">byDate()</code>: The value taken from the response via the provided JSON Path must
|
||||
match the regex for an ISO Date value.</li><li class="listitem"><code class="literal">byTimestamp()</code>: The value taken from the response via the provided JSON Path must
|
||||
@@ -746,7 +1020,15 @@ unflattened collection, use a custom method with the <code class="literal">byCom
|
||||
passed as an input to the custom method that you provide. For example,
|
||||
<code class="literal">byCommand('foo($it)')</code> results in calling a <code class="literal">foo</code> method to which the value matching the
|
||||
JSON Path gets passed. The type of the object read from the JSON can be one of the
|
||||
following, depending on the JSON path:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><code class="literal">String</code>: If you point to a <code class="literal">String</code> value.</li><li class="listitem"><code class="literal">JSONArray</code>: If you point to a <code class="literal">List</code>.</li><li class="listitem"><code class="literal">Map</code>: If you point to a <code class="literal">Map</code>.</li><li class="listitem"><code class="literal">Number</code>: If you point to <code class="literal">Integer</code>, <code class="literal">Double</code>, or other kind of number.</li><li class="listitem"><code class="literal">Boolean</code>: If you point to a <code class="literal">Boolean</code>.</li></ul></div></li></ul></div></li></ul></div><p>Consider the following example:</p><pre class="programlisting">Contract contractDsl = Contract.make {
|
||||
following, depending on the JSON path:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><code class="literal">String</code>: If you point to a <code class="literal">String</code> value.</li><li class="listitem"><code class="literal">JSONArray</code>: If you point to a <code class="literal">List</code>.</li><li class="listitem"><code class="literal">Map</code>: If you point to a <code class="literal">Map</code>.</li><li class="listitem"><code class="literal">Number</code>: If you point to <code class="literal">Integer</code>, <code class="literal">Double</code>, or other kind of number.</li><li class="listitem"><code class="literal">Boolean</code>: If you point to a <code class="literal">Boolean</code>.</li></ul></div></li></ul></div></li></ul></div><p><b>YAML. </b><span class="emphasis"><em>Please read the Groovy section for detailed explanation of
|
||||
what the types mean</em></span></p><p>For YAML the structure of a matcher looks like this</p><pre class="programlisting">- path: $.foo
|
||||
type: by_regex
|
||||
value: bar</pre><p>Or if you want to use one of the predefined regular expressions
|
||||
<code class="literal">[only_alpha_unicode, number, any_boolean, ip_address, hostname,
|
||||
email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_empty, non_blank]</code>:</p><pre class="programlisting">- path: $.foo
|
||||
type: by_regex
|
||||
predefined: only_alpha_unicode</pre><p>Below you can find the allowed list of `type`s.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">For <code class="literal">stubMatchers</code>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><code class="literal">by_equality</code></li><li class="listitem"><code class="literal">by_regex</code></li><li class="listitem"><code class="literal">by_date</code></li><li class="listitem"><code class="literal">by_timestamp</code></li><li class="listitem"><code class="literal">by_time</code></li></ul></div></li><li class="listitem"><p class="simpara">For <code class="literal">testMatchers</code>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><code class="literal">by_equality</code></li><li class="listitem"><code class="literal">by_regex</code></li><li class="listitem"><code class="literal">by_date</code></li><li class="listitem"><code class="literal">by_timestamp</code></li><li class="listitem"><code class="literal">by_time</code></li><li class="listitem"><p class="simpara"><code class="literal">by_type</code></p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; "><li class="listitem">there are 2 additional fields accepted: <code class="literal">minOccurrence</code> and <code class="literal">maxOccurrence</code>.</li></ul></div></li><li class="listitem"><code class="literal">by_command</code></li></ul></div></li></ul></div><p>Consider the following example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
|
||||
urlPath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/get'</span>
|
||||
@@ -852,7 +1134,133 @@ following, depending on the JSON path:</p><div class="itemizedlist"><ul class="i
|
||||
contentType(applicationJson())
|
||||
}
|
||||
}
|
||||
}</pre><p>In the preceding example, you can see the dynamic portions of the contract in the
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request:
|
||||
method: GET
|
||||
urlPath: /get
|
||||
body:
|
||||
duck: 123
|
||||
alpha: "abc"
|
||||
number: 123
|
||||
aBoolean: true
|
||||
date: "2017-01-01"
|
||||
dateTime: "2017-01-01T01:23:45"
|
||||
time: "01:02:34"
|
||||
valueWithoutAMatcher: "foo"
|
||||
valueWithTypeMatch: "string"
|
||||
key:
|
||||
"complex.key": 'foo'
|
||||
matchers:
|
||||
headers:
|
||||
- key: Content-Type
|
||||
regex: "application/json.*"
|
||||
body:
|
||||
- path: $.duck
|
||||
type: by_regex
|
||||
value: "[0-9]{3}"
|
||||
- path: $.duck
|
||||
type: by_equality
|
||||
- path: $.alpha
|
||||
type: by_regex
|
||||
predefined: only_alpha_unicode
|
||||
- path: $.alpha
|
||||
type: by_equality
|
||||
- path: $.number
|
||||
type: by_regex
|
||||
predefined: number
|
||||
- path: $.aBoolean
|
||||
type: by_regex
|
||||
predefined: any_boolean
|
||||
- path: $.date
|
||||
type: by_date
|
||||
- path: $.dateTime
|
||||
type: by_timestamp
|
||||
- path: $.time
|
||||
type: by_time
|
||||
- path: "$.['key'].['complex.key']"
|
||||
type: by_equality
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
response:
|
||||
status: 200
|
||||
body:
|
||||
duck: 123
|
||||
alpha: "abc"
|
||||
number: 123
|
||||
aBoolean: true
|
||||
date: "2017-01-01"
|
||||
dateTime: "2017-01-01T01:23:45"
|
||||
time: "01:02:34"
|
||||
valueWithoutAMatcher: "foo"
|
||||
valueWithTypeMatch: "string"
|
||||
valueWithMin:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
valueWithMax:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
valueWithMinMax:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
valueWithMinEmpty: []
|
||||
valueWithMaxEmpty: []
|
||||
key:
|
||||
'complex.key' : 'foo'
|
||||
matchers:
|
||||
headers:
|
||||
- key: Content-Type
|
||||
regex: "application/json.*"
|
||||
body:
|
||||
- path: $.duck
|
||||
type: by_regex
|
||||
value: "[0-9]{3}"
|
||||
- path: $.duck
|
||||
type: by_equality
|
||||
- path: $.alpha
|
||||
type: by_regex
|
||||
predefined: only_alpha_unicode
|
||||
- path: $.alpha
|
||||
type: by_equality
|
||||
- path: $.number
|
||||
type: by_regex
|
||||
predefined: number
|
||||
- path: $.aBoolean
|
||||
type: by_regex
|
||||
predefined: any_boolean
|
||||
- path: $.date
|
||||
type: by_date
|
||||
- path: $.dateTime
|
||||
type: by_timestamp
|
||||
- path: $.time
|
||||
type: by_time
|
||||
- path: $.valueWithTypeMatch
|
||||
type: by_type
|
||||
- path: $.valueWithMin
|
||||
type: by_type
|
||||
minOccurrence: 1
|
||||
- path: $.valueWithMax
|
||||
type: by_type
|
||||
maxOccurrence: 3
|
||||
- path: $.valueWithMinMax
|
||||
type: by_type
|
||||
minOccurrence: 1
|
||||
maxOccurrence: 3
|
||||
- path: $.valueWithMinEmpty
|
||||
type: by_type
|
||||
minOccurrence: 0
|
||||
- path: $.valueWithMaxEmpty
|
||||
type: by_type
|
||||
maxOccurrence: 0
|
||||
- path: $.duck
|
||||
type: by_command
|
||||
value: assertThatValueIsANumber($it)
|
||||
headers:
|
||||
Content-Type: application/json</pre><p>
|
||||
</p><p>In the preceding example, you can see the dynamic portions of the contract in the
|
||||
<code class="literal">matchers</code> sections. For the request part, you can see that, for all fields but
|
||||
<code class="literal">valueWithoutAMatcher</code>, the values of the regular expressions that the stub should
|
||||
contain are explicitly set. For the <code class="literal">valueWithoutAMatcher</code>, the verification takes place
|
||||
@@ -908,51 +1316,51 @@ statically imported to your tests. Notice that the <code class="literal">byComma
|
||||
the method name and passed the proper JSON path as a parameter to it.</p></td></tr></table></div><p>The resulting WireMock stub is in the following example:</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"urlPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/get"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"POST"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matches"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json.*"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bodyPatterns"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['valueWithoutAMatcher'] == 'foo')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['valueWithTypeMatch'] == 'string')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['list'].['some'].['nested'][?(@.['anothervalue'] == 4)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['list'].['someother'].['nested'][?(@.['anothervalue'] == 4)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['list'].['someother'].['nested'][?(@.['json'] == 'with value')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.duck =~ /([0-9]{3})/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.duck == 123)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.alpha =~ /([\\\\p{L}]*)/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.alpha == 'abc')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.number =~ /(-?(\\\\d*\\\\.\\\\d+|\\\\d+))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.aBoolean =~ /((true|false))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.date =~ /((\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.dateTime =~ /(([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.time =~ /((2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.list.some.nested[?(@.json =~ /(.*)/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"urlPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/get"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"POST"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matches"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json.*"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bodyPatterns"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['valueWithoutAMatcher'] == 'foo')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.['valueWithTypeMatch'] == 'string')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['list'].['some'].['nested'][?(@.['anothervalue'] == 4)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['list'].['someother'].['nested'][?(@.['anothervalue'] == 4)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.['list'].['someother'].['nested'][?(@.['json'] == 'with value')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.duck =~ /([0-9]{3})/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.duck == 123)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.alpha =~ /([\\\\p{L}]*)/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.alpha == 'abc')]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.number =~ /(-?(\\\\d*\\\\.\\\\d+|\\\\d+))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.aBoolean =~ /((true|false))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.date =~ /((\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.dateTime =~ /(([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.time =~ /((2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]))/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.list.some.nested[?(@.json =~ /(.*)/)]"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>date\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>dateTime\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>T01:<span class="hl-number">23</span>:<span class="hl-number">45</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>number\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>aBoolean\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":true,\\"</span>duck\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>alpha\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>abc\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMin\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>time\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">01</span>:<span class="hl-number">02</span>:<span class="hl-number">34</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithTypeMatch\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>string\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithMinMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithoutAMatcher\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <span class="hl-number">200</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>date\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>dateTime\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">2017</span>-<span class="hl-number">01</span>-<span class="hl-number">01</span>T01:<span class="hl-number">23</span>:<span class="hl-number">45</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>number\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>aBoolean\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":true,\\"</span>duck\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>alpha\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>abc\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMin\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>time\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">01</span>:<span class="hl-number">02</span>:<span class="hl-number">34</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithTypeMatch\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>string\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithMinMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithoutAMatcher\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</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 use a <code class="literal">matcher</code>, then the part of the request aned response that the
|
||||
@@ -1021,7 +1429,8 @@ content type set. Otherwise, the default of <code class="literal">application/oc
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['property1']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_async_support" href="#_async_support"></a>8.7 Async Support</h2></div></div></div><p>If you’re using asynchronous communication on the server side (your controllers are
|
||||
returning <code class="literal">Callable</code>, <code class="literal">DeferredResult</code>, and so on), then, inside your contract, you must
|
||||
provide a <code class="literal">sync()</code> method in the <code class="literal">response</code> section. The following code shows an example:</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
provide a <code class="literal">sync()</code> method in the <code class="literal">response</code> section. The following code shows an example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method GET()
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/get'</span>
|
||||
@@ -1031,7 +1440,11 @@ provide a <code class="literal">sync()</code> method in the <code class="literal
|
||||
body <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Passed'</span>
|
||||
async()
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_working_with_context_paths" href="#_working_with_context_paths"></a>8.8 Working with Context Paths</h2></div></div></div><p>Spring Cloud Contract supports context paths.</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>The only change needed to fully support context paths is the switch on the
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">response:
|
||||
async: true</pre><p>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_working_with_context_paths" href="#_working_with_context_paths"></a>8.8 Working with Context Paths</h2></div></div></div><p>Spring Cloud Contract supports context paths.</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>The only change needed to fully support context paths is the switch on the
|
||||
<span class="strong"><strong>PRODUCER</strong></span> side. Also, the autogenerated tests must use <span class="strong"><strong>EXPLICIT</strong></span> mode. The consumer
|
||||
side remains untouched. In order for the generated test to pass, you must use <span class="strong"><strong>EXPLICIT</strong></span>
|
||||
mode.</p></td></tr></table></div><p class="primary"><b>Maven. </b>
|
||||
@@ -1077,7 +1490,8 @@ socket.</p><p>Consider the following contract:</p><pre class="programlisting">or
|
||||
context path included (for example, <code class="literal">/my-context-path/url</code>).</li><li class="listitem">Your contracts reflect that you have a context path. Your generated stubs also have
|
||||
that information (for example, in the stubs, you have to call <code class="literal">/my-context-path/url</code>).</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_messaging_top_level_elements" href="#_messaging_top_level_elements"></a>8.9 Messaging Top-Level Elements</h2></div></div></div><p>The DSL for messaging looks a little bit different than the one that focuses on HTTP. The
|
||||
following sections explain the differences:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-output-triggered-method" title="8.9.1 Output Triggered by a Method">Section 8.9.1, “Output Triggered by a Method”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-output-triggered-message" title="8.9.2 Output Triggered by a Message">Section 8.9.2, “Output Triggered by a Message”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-consumer-producer" title="8.9.3 Consumer/Producer">Section 8.9.3, “Consumer/Producer”</a></li><li class="listitem"><a class="xref" href="multi__contract_dsl.html#contract-dsl-common" title="8.9.4 Common">Section 8.9.4, “Common”</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-output-triggered-method" href="#contract-dsl-output-triggered-method"></a>8.9.1 Output Triggered by a Method</h3></div></div></div><p>The output message can be triggered by calling a method (such as a <code class="literal">Scheduler</code> when a was
|
||||
started and a message was sent), as shown in the following example:</p><pre class="programlisting">def dsl = Contract.make {
|
||||
started and a message was sent), as shown in the following example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">def dsl = 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">'Some description'</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Label by means of which the output message can be triggered</span>
|
||||
@@ -1098,11 +1512,31 @@ started and a message was sent), as shown in the following example:</p><pre clas
|
||||
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>In the previous example case, the output message is sent to <code class="literal">output</code> if a method called
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting"># Human readable description
|
||||
description: Some description
|
||||
# Label by means of which the output message can be triggered
|
||||
label: some_label
|
||||
input:
|
||||
# the contract will be triggered by a method
|
||||
triggeredBy: bookReturnedTriggered()
|
||||
# output message of the contract
|
||||
outputMessage:
|
||||
# destination to which the output message will be sent
|
||||
sentTo: output
|
||||
# the body of the output message
|
||||
body:
|
||||
bookName: foo
|
||||
# the headers of the output message
|
||||
headers:
|
||||
BOOK-NAME: foo</pre><p>
|
||||
</p><p>In the previous example case, the output message is sent to <code class="literal">output</code> if a method called
|
||||
<code class="literal">bookReturnedTriggered</code> is executed. On the message <span class="strong"><strong>publisher’s</strong></span> side, we generate a
|
||||
test that calls that method to trigger the message. On the <span class="strong"><strong>consumer</strong></span> side, you can use
|
||||
the <code class="literal">some_label</code> to trigger the message.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-output-triggered-message" href="#contract-dsl-output-triggered-message"></a>8.9.2 Output Triggered by a Message</h3></div></div></div><p>The output message can be triggered by receiving a message, as shown in the following
|
||||
example:</p><pre class="programlisting">def dsl = Contract.make {
|
||||
example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">def dsl = Contract.make {
|
||||
description <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Some Description'</span>
|
||||
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// input is a message</span>
|
||||
@@ -1127,11 +1561,36 @@ example:</p><pre class="programlisting">def dsl = Contract.make {
|
||||
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>In the preceding example, the output message is sent to <code class="literal">output</code> if a proper message is
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting"># Human readable description
|
||||
description: Some description
|
||||
# Label by means of which the output message can be triggered
|
||||
label: some_label
|
||||
# input is a message
|
||||
input:
|
||||
messageFrom: input
|
||||
# has the following body
|
||||
messageBody:
|
||||
bookName: 'foo'
|
||||
# and the following headers
|
||||
messageHeaders:
|
||||
sample: 'header'
|
||||
# output message of the contract
|
||||
outputMessage:
|
||||
# destination to which the output message will be sent
|
||||
sentTo: output
|
||||
# the body of the output message
|
||||
body:
|
||||
bookName: foo
|
||||
# the headers of the output message
|
||||
headers:
|
||||
BOOK-NAME: foo</pre><p>
|
||||
</p><p>In the preceding example, the output message is sent to <code class="literal">output</code> if a proper message is
|
||||
received on the <code class="literal">input</code> destination. On the message <span class="strong"><strong>publisher’s</strong></span> side, the engine
|
||||
generates a test that sends the input message to the defined destination. On the
|
||||
<span class="strong"><strong>consumer</strong></span> side, you can either send a message to the input destination or use a label
|
||||
(<code class="literal">some_label</code> in the example) to trigger the message.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-consumer-producer" href="#contract-dsl-consumer-producer"></a>8.9.3 Consumer/Producer</h3></div></div></div><p>In HTTP, you have a notion of <code class="literal">client</code>/<code class="literal">stub and `server</code>/<code class="literal">test</code> notation. You can also
|
||||
(<code class="literal">some_label</code> in the example) to trigger the message.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-consumer-producer" href="#contract-dsl-consumer-producer"></a>8.9.3 Consumer/Producer</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL.</p></td></tr></table></div><p>In HTTP, you have a notion of <code class="literal">client</code>/<code class="literal">stub and `server</code>/<code class="literal">test</code> notation. You can also
|
||||
use those paradigms in messaging. In addition, Spring Cloud Contract Verifier also
|
||||
provides the <code class="literal">consumer</code> and <code class="literal">producer</code> methods, as presented in the following example
|
||||
(note that you can use either <code class="literal">$</code> or <code class="literal">value</code> methods to provide <code class="literal">consumer</code> and <code class="literal">producer</code>
|
||||
@@ -1152,11 +1611,12 @@ parts):</p><pre class="programlisting">Contract.make {
|
||||
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
|
||||
])
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-common" href="#contract-dsl-common"></a>8.9.4 Common</h3></div></div></div><p>In the <code class="literal">input {}</code> or <code class="literal">outputMessage {}</code> section you can call <code class="literal">assertThat</code> with the name
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="contract-dsl-common" href="#contract-dsl-common"></a>8.9.4 Common</h3></div></div></div><p>In the <code class="literal">input</code> or <code class="literal">outputMessage</code> section you can call <code class="literal">assertThat</code> with the name
|
||||
of a <code class="literal">method</code> (e.g. <code class="literal">assertThatMessageIsOnTheQueue()</code>) that you have defined in the
|
||||
base class or in a static import. Spring Cloud Pipelines will execute that method
|
||||
in the genertaed test.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_multiple_contracts_in_one_file" href="#_multiple_contracts_in_one_file"></a>8.10 Multiple Contracts in One File</h2></div></div></div><p>You can define multiple contracts in one file. Such a contract might resemble the
|
||||
following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
base class or in a static import. Spring Cloud Contract will execute that method
|
||||
in the generated test.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_multiple_contracts_in_one_file" href="#_multiple_contracts_in_one_file"></a>8.10 Multiple Contracts in One File</h2></div></div></div><p>You can define multiple contracts in one file. Such a contract might resemble the
|
||||
following example:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
[
|
||||
Contract.make {
|
||||
@@ -1178,7 +1638,23 @@ following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.
|
||||
status <span class="hl-number">200</span>
|
||||
}
|
||||
}
|
||||
]</pre><p>In the preceding example, one contract has the <code class="literal">name</code> field and the other does not. This
|
||||
]</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">---
|
||||
name: should post a user
|
||||
request:
|
||||
method: POST
|
||||
url: /users/1
|
||||
response:
|
||||
status: 200
|
||||
|
||||
---
|
||||
request:
|
||||
method: POST
|
||||
url: /users/2
|
||||
response:
|
||||
status: 200</pre><p>
|
||||
</p><p>In the preceding example, one contract has the <code class="literal">name</code> field and the other does not. This
|
||||
leads to generation of two tests that look more or less like this:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.verifier.tests.com.hello;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.example.TestBase;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>9. 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. Contract DSL"><link rel="next" href="multi__using_the_pluggable_architecture.html" title="10. 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. Customization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <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. Customization</h1></div></div></div><p>You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in
|
||||
<title>9. 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. Contract DSL"><link rel="next" href="multi__using_the_pluggable_architecture.html" title="10. 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. Customization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <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. 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 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 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;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>3. Spring Cloud Contract FAQ</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_introduction.html" title="2. Spring Cloud Contract Verifier Introduction"><link rel="next" href="multi__spring_cloud_contract_verifier_setup.html" title="4. Spring Cloud Contract Verifier Setup"></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">3. Spring Cloud Contract FAQ</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_introduction.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_setup.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_faq" href="#_spring_cloud_contract_faq"></a>3. Spring Cloud Contract FAQ</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_use_spring_cloud_contract_verifier_and_not_x" href="#_why_use_spring_cloud_contract_verifier_and_not_x"></a>3.1 Why use Spring Cloud Contract Verifier and not X ?</h2></div></div></div><p>For the time being Spring Cloud Contract Verifier is a JVM based tool. So it could be your first pick when you’re already creating
|
||||
software for the JVM. This project has a lot of really interesting features but especially quite a few of them definitely make
|
||||
Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Contract (CDC) tooling. Out of many the most interesting are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Possibility to do CDC with messaging</li><li class="listitem">Clear and easy to use, statically typed DSL</li><li class="listitem">Possibility to copy paste your current JSON file to the contract and only edit its elements</li><li class="listitem">Automatic generation of tests from the defined Contract</li><li class="listitem">Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory</li><li class="listitem">Spring Cloud integration - no discovery service is needed for integration tests</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_what_is_this_value_consumer_producer" href="#_what_is_this_value_consumer_producer"></a>3.2 What is this value(consumer(), producer()) ?</h2></div></div></div><p>One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
|
||||
Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Contract (CDC) tooling. Out of many the most interesting are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Possibility to do CDC with messaging</li><li class="listitem">Clear and easy to use, statically typed DSL</li><li class="listitem">Possibility to copy paste your current JSON file to the contract and only edit its elements</li><li class="listitem">Automatic generation of tests from the defined Contract</li><li class="listitem">Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory</li><li class="listitem">Spring Cloud integration - no discovery service is needed for integration tests</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_i_don_t_want_to_write_a_contract_in_groovy" href="#_i_don_t_want_to_write_a_contract_in_groovy"></a>3.2 I don’t want to write a contract in Groovy!</h2></div></div></div><p>No problem. You can write a contract in YAML!</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_what_is_this_value_consumer_producer" href="#_what_is_this_value_consumer_producer"></a>3.3 What is this value(consumer(), producer()) ?</h2></div></div></div><p>One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
|
||||
What typically makes that difficult are the hard-coded values of request / response elements. For example dates or ids.
|
||||
Imagine the following JSON request</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2016-10-10 20:10:15"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
@@ -68,19 +68,19 @@ for time and UUID are simplified and most likely invalid but we want to keep thi
|
||||
])
|
||||
}
|
||||
}</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>Please read the <a class="link" href="http://groovy-lang.org/json.html" target="_top">Groovy docs related to JSON</a> to understand how to
|
||||
properly structure the request / response bodies.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_do_stubs_versioning" href="#_how_to_do_stubs_versioning"></a>3.3 How to do Stubs versioning?</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_api_versioning" href="#_api_versioning"></a>3.3.1 API Versioning</h3></div></div></div><p>Let’s try to answer a question what versioning really means. If you’re referring to the API version then there are
|
||||
properly structure the request / response bodies.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_do_stubs_versioning" href="#_how_to_do_stubs_versioning"></a>3.4 How to do Stubs versioning?</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_api_versioning" href="#_api_versioning"></a>3.4.1 API Versioning</h3></div></div></div><p>Let’s try to answer a question what versioning really means. If you’re referring to the API version then there are
|
||||
different approaches.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">use Hypermedia, links and do not version your API by any means</li><li class="listitem">pass versions through headers / urls</li></ul></div><p>I will not try to answer a question which approach is better. Whatever suit your needs and allows you to generate
|
||||
business value should be picked.</p><p>Let’s assume that you do version your API. In that case you should provide as many contracts as many versions you support.
|
||||
You can create a subfolder for every version or append it to th contract name - whatever suits you more.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_jar_versioning" href="#_jar_versioning"></a>3.3.2 JAR versioning</h3></div></div></div><p>If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.</p><p>Let’s assume that you’re doing Continuous Delivery / Deployment which means that you’re generating a new version of
|
||||
You can create a subfolder for every version or append it to th contract name - whatever suits you more.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_jar_versioning" href="#_jar_versioning"></a>3.4.2 JAR versioning</h3></div></div></div><p>If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.</p><p>Let’s assume that you’re doing Continuous Delivery / Deployment which means that you’re generating a new version of
|
||||
the jar each time you go through the pipeline and that jar can go to production at any time. For example your jar version
|
||||
looks like this (it got built on the 20.10.2016 at 20:15:21) :</p><pre class="programlisting"><span class="hl-number">1.0</span>.<span class="hl-number">0.20161020</span>-<span class="hl-number">201521</span>-RELEASE</pre><p>In that case your generated stub jar will look like this.</p><pre class="programlisting"><span class="hl-number">1.0</span>.<span class="hl-number">0.20161020</span>-<span class="hl-number">201521</span>-RELEASE-stubs.jar</pre><p>In this case you should inside your <code class="literal">application.yml</code> or <code class="literal">@AutoConfigureStubRunner</code> when referencing stubs provide the
|
||||
latest version of the stubs. You can do that by passing the <code class="literal">+</code> sign. Example</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:stubs:8080"</span>})</pre><p>If the versioning however is fixed (e.g. <code class="literal">1.0.4.RELEASE</code> or <code class="literal">2.1.1</code>) then you have to set the concrete value of the jar
|
||||
version. Example for 2.1.1.</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:2.1.1:stubs:8080"</span>})</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dev_or_prod_stubs" href="#_dev_or_prod_stubs"></a>3.3.3 Dev or prod stubs</h3></div></div></div><p>You can manipulate the classifier to run the tests against current development version of the stubs of other services
|
||||
version. Example for 2.1.1.</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:2.1.1:stubs:8080"</span>})</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dev_or_prod_stubs" href="#_dev_or_prod_stubs"></a>3.4.3 Dev or prod stubs</h3></div></div></div><p>You can manipulate the classifier to run the tests against current development version of the stubs of other services
|
||||
or the ones that were deployed to production. If you alter your build to deploy the stubs with the <code class="literal">prod-stubs</code> classifier
|
||||
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.</p><p>Example of tests using development version of stubs</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:stubs:8080"</span>})</pre><p>Example of tests using production version of stubs</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:prod-stubs:8080"</span>})</pre><p>You can pass those values also via properties from your deployment pipeline.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_common_repo_with_contracts" href="#_common_repo_with_contracts"></a>3.4 Common repo with contracts</h2></div></div></div><p>Another way of storing contracts other than having them with the producer is keeping them in a common place.
|
||||
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.</p><p>Example of tests using development version of stubs</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:stubs:8080"</span>})</pre><p>Example of tests using production version of stubs</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:prod-stubs:8080"</span>})</pre><p>You can pass those values also via properties from your deployment pipeline.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_common_repo_with_contracts" href="#_common_repo_with_contracts"></a>3.5 Common repo with contracts</h2></div></div></div><p>Another way of storing contracts other than having them with the producer is keeping them in a common place.
|
||||
It can be related to security issues where the consumers can’t clone the producer’s code. Also if you keep
|
||||
contracts in a single place then you, as a producer, will know how many consumers you have and which
|
||||
consumer will you break with your local changes.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_repo_structure" href="#_repo_structure"></a>3.4.1 Repo structure</h3></div></div></div><p>Let’s assume that we have a producer with coordinates <code class="literal">com.example:server</code> and 3 consumers: <code class="literal">client1</code>,
|
||||
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 Repo structure</h3></div></div></div><p>Let’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/1.0.x/samples/standalone/contracts" target="_top">here</a>:</p><pre class="programlisting">├── com
|
||||
│ └── example
|
||||
@@ -115,7 +115,7 @@ one to one to the contents of the repo.</p><p>Example of a <code class="literal"
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><parent></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>2.0.0.M6<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>2.0.0.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><relativePath /></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></parent></span>
|
||||
|
||||
@@ -271,11 +271,11 @@ Those poms are necessary for the consumer side to run <code class="literal">mvn
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></excludes></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></fileSet></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></fileSets></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></assembly></span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_workflow" href="#_workflow"></a>3.4.2 Workflow</h3></div></div></div><p>The workflow would look similar to the one presented in the <code class="literal">Step by step guide to CDC</code>. The only difference
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></assembly></span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_workflow" href="#_workflow"></a>3.5.2 Workflow</h3></div></div></div><p>The workflow would look similar to the one presented in the <code class="literal">Step by step guide to CDC</code>. The only difference
|
||||
is that the producer doesn’t own the contracts anymore. So the consumer and the producer have to work on
|
||||
common contracts in a common repository.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer" href="#_consumer"></a>3.4.3 Consumer</h3></div></div></div><p>When the <span class="strong"><strong>consumer</strong></span> wants to work on the contracts offline, instead of cloning the producer code, the
|
||||
common contracts in a common repository.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer" href="#_consumer"></a>3.5.3 Consumer</h3></div></div></div><p>When the <span class="strong"><strong>consumer</strong></span> wants to work on the contracts offline, instead of cloning the producer code, the
|
||||
consumer team clones the common repository, goes to the required producer’s folder (e.g. <code class="literal">com/example/server</code>)
|
||||
and runs <code class="literal">mvn clean install -DskipTests</code> to install locally the stubs converted from the contracts.</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 need to have <a class="link" href="http://maven.apache.org/download.cgi" target="_top">Maven installed locally</a></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer" href="#_producer"></a>3.4.4 Producer</h3></div></div></div><p>As a <span class="strong"><strong>producer</strong></span> it’s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
|
||||
and runs <code class="literal">mvn clean install -DskipTests</code> to install locally the stubs converted from the contracts.</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 need to have <a class="link" href="http://maven.apache.org/download.cgi" target="_top">Maven installed locally</a></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer" href="#_producer"></a>3.5.4 Producer</h3></div></div></div><p>As a <span class="strong"><strong>producer</strong></span> it’s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
|
||||
of the JAR containing the contracts:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
@@ -291,12 +291,13 @@ of the JAR containing the contracts:</p><pre class="programlisting"><span xmlns:
|
||||
from <code class="literal"><a class="link" href="http://link/to/your/nexus/or/artifactory/or/sth" target="_top">http://link/to/your/nexus/or/artifactory/or/sth</a></code>. It will be then unpacked in a local temporary folder
|
||||
and contracts present under the <code class="literal">com/example/server</code> will be picked as the ones used to generate the
|
||||
tests and the stubs. Due to this convention the producer team will know which consumer teams will be broken
|
||||
when some incompatible changes are done.</p><p>The rest of the flow looks the same.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_can_i_have_multiple_base_classes_for_tests" href="#_can_i_have_multiple_base_classes_for_tests"></a>3.5 Can I have multiple base classes for tests?</h2></div></div></div><p>Yes! Check out the <a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_different_base_classes_for_contracts" target="_top">Different base classes for contracts</a> sections
|
||||
of either Gradle or Maven plugins.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client" href="#_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client"></a>3.6 How can I debug the request/response being sent by the generated tests client?</h2></div></div></div><p>The generated tests all boil down to RestAssured in some form or fashion which relies on <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/" target="_top">Apache HttpClient</a>. HttpClient has a facility called <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging" target="_top">wire logging</a> which logs the entire request and response to HttpClient. Spring Boot has a logging <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_top">common application property</a> for doing this sort of thing, just add this to your application properties</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.org.apache.http.wire</span>=DEBUG</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock" href="#_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock"></a>3.6.1 How can I debug the mapping/request/response being sent by WireMock?</h3></div></div></div><p>Starting from version <code class="literal">1.2.0</code> we turn on WireMock logging to
|
||||
when some incompatible changes are done.</p><p>The rest of the flow looks the same.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_can_i_have_multiple_base_classes_for_tests" href="#_can_i_have_multiple_base_classes_for_tests"></a>3.6 Can I have multiple base classes for tests?</h2></div></div></div><p>Yes! Check out the <a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_different_base_classes_for_contracts" target="_top">Different base classes for contracts</a> sections
|
||||
of either Gradle or Maven plugins.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client" href="#_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client"></a>3.7 How can I debug the request/response being sent by the generated tests client?</h2></div></div></div><p>The generated tests all boil down to RestAssured in some form or fashion which relies on <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/" target="_top">Apache HttpClient</a>. HttpClient has a facility called <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging" target="_top">wire logging</a> which logs the entire request and response to HttpClient. Spring Boot has a logging <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_top">common application property</a> for doing this sort of thing, just add this to your application properties</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.org.apache.http.wire</span>=DEBUG</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock" href="#_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock"></a>3.7.1 How can I debug the mapping/request/response being sent by WireMock?</h3></div></div></div><p>Starting from version <code class="literal">1.2.0</code> we turn on WireMock logging to
|
||||
info and the WireMock notifier to being verbose. Now you will
|
||||
exactly know what request was received by WireMock server and which
|
||||
matching response definition was picked.</p><p>To turn off this feature just bump WireMock logging to <code class="literal">ERROR</code></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.com.github.tomakehurst.wiremock</span>=ERROR</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_see_what_got_registered_in_the_http_server_stub" href="#_how_can_i_see_what_got_registered_in_the_http_server_stub"></a>3.6.2 How can I see what got registered in the HTTP server stub?</h3></div></div></div><p>You can use the <code class="literal">mappingsOutputFolder</code> property on <code class="literal">@AutoConfigureStubRunner</code> or <code class="literal">StubRunnerRule</code>
|
||||
matching response definition was picked.</p><p>To turn off this feature just bump WireMock logging to <code class="literal">ERROR</code></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.com.github.tomakehurst.wiremock</span>=ERROR</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_see_what_got_registered_in_the_http_server_stub" href="#_how_can_i_see_what_got_registered_in_the_http_server_stub"></a>3.7.2 How can I see what got registered in the HTTP server stub?</h3></div></div></div><p>You can use the <code class="literal">mappingsOutputFolder</code> property on <code class="literal">@AutoConfigureStubRunner</code> or <code class="literal">StubRunnerRule</code>
|
||||
to dump all mappings per artifact id. Also the port at which the given stub server was
|
||||
started will be attached.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_can_i_reference_the_request_from_the_response" href="#_can_i_reference_the_request_from_the_response"></a>3.6.3 Can I reference the request from the response?</h3></div></div></div><p>Yes! With version 1.1.0 we’ve added such a possibility. On the HTTP stub server side we’re providing support
|
||||
for this for WireMock. In case of other HTTP server stubs you’ll have to implement the approach yourself.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_can_i_reference_text_from_file" href="#_can_i_reference_text_from_file"></a>3.6.4 Can I reference text from file?</h3></div></div></div><p>Yes! With version 1.2.0 we’ve added such a possibility. It’s enough to call <code class="literal">file(…​)</code> method in the
|
||||
DSL and provide a path relative to where the contract lays.</p></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_introduction.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Spring Cloud Contract Verifier Introduction </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"> 4. Spring Cloud Contract Verifier Setup</td></tr></table></div></body></html>
|
||||
started will be attached.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_can_i_reference_the_request_from_the_response" href="#_can_i_reference_the_request_from_the_response"></a>3.7.3 Can I reference the request from the response?</h3></div></div></div><p>Yes! With version 1.1.0 we’ve added such a possibility. On the HTTP stub server side we’re providing support
|
||||
for this for WireMock. In case of other HTTP server stubs you’ll have to implement the approach yourself.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_can_i_reference_text_from_file" href="#_can_i_reference_text_from_file"></a>3.7.4 Can I reference text from file?</h3></div></div></div><p>Yes! With version 1.2.0 we’ve added such a possibility. It’s enough to call <code class="literal">file(…​)</code> method in the
|
||||
DSL and provide a path relative to where the contract lays.
|
||||
If you’re using YAML just use the <code class="literal">bodyFromFile</code> property.</p></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_introduction.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Spring Cloud Contract Verifier Introduction </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"> 4. Spring Cloud Contract Verifier Setup</td></tr></table></div></body></html>
|
||||
@@ -89,9 +89,7 @@ it if you want to.</p></td></tr></table></div><p class="primary"><b>Maven.
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><inherited></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></inherited></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><attach></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></attach></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><descriptors></span>
|
||||
${basedir}/src/assembly/stub.xml
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></descriptors></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><descriptor></span>${basedir}/src/assembly/stub.xml<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></descriptor></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></execution></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></executions></span>
|
||||
@@ -688,4 +686,29 @@ pass an empty classifier this way: <code class="literal">groupId:artifactId:vers
|
||||
downloaded.</li></ul></div><p><code class="literal">port</code> means the port of the WireMock server.</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>Starting with version 1.0.4, you can provide a range of versions that you
|
||||
would like the Stub Runner to take into consideration. You can read more about the
|
||||
<a class="link" href="https://wiki.eclipse.org/Aether/New_and_Noteworthy#Version_Ranges" target="_top">Aether versioning
|
||||
ranges here</a>.</p></td></tr></table></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_messaging.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__stub_runner_for_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Spring Cloud Contract Verifier Messaging </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Stub Runner for Messaging</td></tr></table></div></body></html>
|
||||
ranges here</a>.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="stubrunner-docker" href="#stubrunner-docker"></a>6.9 Stub Runner Docker</h2></div></div></div><p>We’re publishing a <code class="literal">spring-cloud/spring-cloud-contract-stub-runner</code> Docker image
|
||||
that will start the standalone version of Stub Runner.</p><p>If you want to learn more about the basics of Maven, artifact ids,
|
||||
group ids, classifiers and Artifact Managers, just click here <a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#docker-project" title="4.5 Docker Project">Section 4.5, “Docker Project”</a>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_to_use_it_2" href="#_how_to_use_it_2"></a>6.9.1 How to use it</h3></div></div></div><p>Just execute the docker image. You can pass any of the <a class="xref" href="multi__spring_cloud_contract_stub_runner.html#common-properties-junit-spring" title="6.8.1 Common Properties for JUnit and Spring">Section 6.8.1, “Common Properties for JUnit and Spring”</a>
|
||||
as environment variables. The convention is that all the
|
||||
letters should be upper case. The camel case notation should
|
||||
and the dot (<code class="literal">.</code>) should be separated via underscore (<code class="literal">_</code>). E.g.
|
||||
the <code class="literal">stubrunner.repositoryRoot</code> property should be represented
|
||||
as a <code class="literal">STUBRUNNER_REPOSITORY_ROOT</code> environment variable.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example_of_client_side_usage_in_a_non_jvm_project" href="#_example_of_client_side_usage_in_a_non_jvm_project"></a>6.9.2 Example of client side usage in a non JVM project</h3></div></div></div><p>We’d like to use the stubs created in this <a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#docker-server-side" title="4.5.4 Server side (nodejs)">Section 4.5.4, “Server side (nodejs)”</a> step.
|
||||
Let’s assume that we want to run the stubs on port <code class="literal">9876</code>. The NodeJS code
|
||||
is available here:</p><pre class="programlisting">$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
|
||||
$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> bookstore</pre><p>Let’s run the Stub Runner Boot application with the stubs.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Provide the Spring Cloud Contract Docker version</span>
|
||||
$ SC_CONTRACT_DOCKER_VERSION=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"..."</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># The IP at which the app is running and Docker container can reach it</span>
|
||||
$ APP_IP=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"192.168.0.100"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Contract Stub Runner properties</span>
|
||||
$ STUBRUNNER_PORT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"8083"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Stub coordinates 'groupId:artifactId:version:classifier:port'</span>
|
||||
$ STUBRUNNER_IDS=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:bookstore:0.0.1.RELEASE:stubs:9876"</span>
|
||||
$ STUBRUNNER_REPOSITORY_ROOT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://${APP_IP}:8081/artifactory/libs-release-local"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Run the docker with Stub Runner Boot</span>
|
||||
$ docker run --rm -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_IDS=${STUBRUNNER_IDS}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_REPOSITORY_ROOT=${STUBRUNNER_REPOSITORY_ROOT}"</span> -p <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${STUBRUNNER_PORT}:${STUBRUNNER_PORT}"</span> -p <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"9876:9876"</span> springcloud/spring-cloud-contract-stub-runner:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${SC_CONTRACT_DOCKER_VERSION}"</span></pre><p>What’s happening is that</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">a standalone Stub Runner application got started</li><li class="listitem">it downloaded the stub with coordinates <code class="literal">com.example:bookstore:0.0.1.RELEASE:stubs</code> on port <code class="literal">9876</code></li><li class="listitem">it got downloaded from Artifactory running at <code class="literal"><a class="link" href="http://192.168.0.100:8081/artifactory/libs-release-local" target="_top">http://192.168.0.100:8081/artifactory/libs-release-local</a></code></li><li class="listitem">after a while Stub Runner will be running on port <code class="literal">8083</code></li><li class="listitem">and the stubs will be running at port <code class="literal">9876</code></li></ul></div><p>On the server side we built a stateful stub. Let’s use curl to assert
|
||||
that the stubs are setup properly.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># let's execute the first request (no response is returned)</span>
|
||||
$ curl -H <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type:application/json"</span> -X POST --data <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }'</span> http://localhost:<span class="hl-number">9876</span>/api/books
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Now time for the second request</span>
|
||||
$ curl -X GET http://localhost:<span class="hl-number">9876</span>/api/books
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># You will receive contents of the JSON</span></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__spring_cloud_contract_verifier_messaging.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__stub_runner_for_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Spring Cloud Contract Verifier Messaging </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Stub Runner for Messaging</td></tr></table></div></body></html>
|
||||
@@ -27,7 +27,8 @@ contracts, one for the positive case and one for the negative case. Contract tes
|
||||
used to test contracts between applications and not to simulate full behavior.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_it_works" href="#_how_it_works"></a>2.3 How It Works</h2></div></div></div><p>This section explores how Spring Cloud Contract Verifier with Stub Runner works.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_defining_the_contract" href="#_defining_the_contract"></a>2.3.1 Defining the contract</h3></div></div></div><p>As consumers of services, we need to define what exactly we want to achieve. We need to
|
||||
formulate our expectations. That is why we write contracts.</p><p>Assume that you want to send a request containing the ID of a client company and the
|
||||
amount it wants to borrow from us. You also want to send it to the /fraudcheck url via
|
||||
the PUT method.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts
|
||||
the PUT method.</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts
|
||||
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
request { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (1)</span>
|
||||
@@ -83,7 +84,61 @@ From the Producer perspective, in the autogenerated producer-side test:
|
||||
(8) - and JSON body equal to
|
||||
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
|
||||
(9) - with header `Content-Type` matching `application/json.*`
|
||||
*/</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_side" href="#_client_side"></a>2.3.2 Client Side</h3></div></div></div><p>Spring Cloud Contract generates stubs, which you can use during client-side testing.
|
||||
*/</span></pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request: # (1)
|
||||
method: PUT # (2)
|
||||
url: /fraudcheck # (3)
|
||||
body: # (4)
|
||||
"client.id": 1234567890
|
||||
loanAmount: 99999
|
||||
headers: # (5)
|
||||
Content-Type: application/json
|
||||
matchers:
|
||||
body:
|
||||
- path: $.['client.id'] # (6)
|
||||
type: by_regex
|
||||
value: "[0-9]{10}"
|
||||
response: # (7)
|
||||
status: 200 # (8)
|
||||
body: # (9)
|
||||
fraudCheckStatus: "FRAUD"
|
||||
"rejection.reason": "Amount too high"
|
||||
headers: # (10)
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
|
||||
#From the Consumer perspective, when shooting a request in the integration test:
|
||||
#
|
||||
#(1) - If the consumer sends a request
|
||||
#(2) - With the "PUT" method
|
||||
#(3) - to the URL "/fraudcheck"
|
||||
#(4) - with the JSON body that
|
||||
# * has a field `clientId`
|
||||
# * has a field `loanAmount` that is equal to `99999`
|
||||
#(5) - with header `Content-Type` equal to `application/json`
|
||||
#(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}`
|
||||
#(7) - then the response will be sent with
|
||||
#(8) - status equal `200`
|
||||
#(9) - and JSON body equal to
|
||||
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
|
||||
#(10) - with header `Content-Type` equal to `application/json`
|
||||
#
|
||||
#From the Producer perspective, in the autogenerated producer-side test:
|
||||
#
|
||||
#(1) - A request will be sent to the producer
|
||||
#(2) - With the "PUT" method
|
||||
#(3) - to the URL "/fraudcheck"
|
||||
#(4) - with the JSON body that
|
||||
# * has a field `clientId` `1234567890`
|
||||
# * has a field `loanAmount` that is equal to `99999`
|
||||
#(5) - with header `Content-Type` equal to `application/json`
|
||||
#(7) - then the test will assert if the response has been sent with
|
||||
#(8) - status equal `200`
|
||||
#(9) - and JSON body equal to
|
||||
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
|
||||
#(10) - with header `Content-Type` equal to `application/json;charset=UTF-8`</pre><p>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_side" href="#_client_side"></a>2.3.2 Client Side</h3></div></div></div><p>Spring Cloud Contract generates stubs, which you can use during client-side testing.
|
||||
You get a running WireMock instance/Messaging route that simulates the service.
|
||||
You would like to feed that instance with a proper stub definition.</p><p>At some point in time, you need to send a request to the Fraud Detection service.</p><pre class="programlisting">ResponseEntity<FraudServiceResponse> response =
|
||||
restTemplate.exchange(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span> + port + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>, HttpMethod.PUT,
|
||||
@@ -98,7 +153,7 @@ You would like to feed that instance with a proper stub definition.</p><p>At som
|
||||
(or random) port.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_server_side" href="#_server_side"></a>2.3.3 Server Side</h3></div></div></div><p>Since you are developing your stub, you need to be sure that it actually resembles your
|
||||
concrete implementation. You cannot have a situation where your stub acts in one way and
|
||||
your application behaves in a different way, especially in production.</p><p>To ensure that your application behaves the way you define in your stub, tests are
|
||||
generated from the stub you provide.</p><p>The autogenerated test looks like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
generated from the stub you provide.</p><p>The autogenerated test looks, more or less, like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
MockMvcRequestSpecification request = given()
|
||||
@@ -207,9 +262,10 @@ client wants to borrow. You want to send it to the <code class="literal">/fraudc
|
||||
FraudServiceResponse.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);</pre><p>For simplicity, the port of the Fraud Detection service is set to <code class="literal">8080</code>, and the
|
||||
application runs on <code class="literal">8090</code>.</p><p>If you start the test at this point, it breaks, because no service currently runs on port
|
||||
<code class="literal">8080</code>.</p><p><span class="strong"><strong>Clone the Fraud Detection service repository locally.</strong></span></p><p>You can start by playing around with the server side contract. To do so, you must first
|
||||
clone it.</p><pre class="programlisting">git clone https://your-git-server.com/server-side.git local-http-server-repo</pre><p><span class="strong"><strong>Define the contract locally in the repo of Fraud Detection service.</strong></span></p><p>As a consumer, you need to define what exactly you want to achieve. You need to formulate
|
||||
clone it.</p><pre class="programlisting">$ git clone https://your-git-server.com/server-side.git local-http-server-repo</pre><p><span class="strong"><strong>Define the contract locally in the repo of Fraud Detection service.</strong></span></p><p>As a consumer, you need to define what exactly you want to achieve. You need to formulate
|
||||
your expectations. To do so, write the following contract:</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>Place the contract under <code class="literal">src/test/resources/contracts/fraud</code> folder. The <code class="literal">fraud</code> folder
|
||||
is important because the producer’s test base class name references that folder.</p></td></tr></table></div><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts
|
||||
is important because the producer’s test base class name references that folder.</p></td></tr></table></div><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts
|
||||
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
request { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (1)</span>
|
||||
@@ -265,8 +321,63 @@ From the Producer perspective, in the autogenerated producer-side test:
|
||||
(8) - and JSON body equal to
|
||||
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
|
||||
(9) - with header `Content-Type` matching `application/json.*`
|
||||
*/</span></pre><p>The Contract is written using a statically typed Groovy DSL. You might wonder what about
|
||||
those <code class="literal">value(client(…​), server(…​))</code> parts. By using this notation, Spring Cloud
|
||||
*/</span></pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">request: # (1)
|
||||
method: PUT # (2)
|
||||
url: /fraudcheck # (3)
|
||||
body: # (4)
|
||||
"client.id": 1234567890
|
||||
loanAmount: 99999
|
||||
headers: # (5)
|
||||
Content-Type: application/json
|
||||
matchers:
|
||||
body:
|
||||
- path: $.['client.id'] # (6)
|
||||
type: by_regex
|
||||
value: "[0-9]{10}"
|
||||
response: # (7)
|
||||
status: 200 # (8)
|
||||
body: # (9)
|
||||
fraudCheckStatus: "FRAUD"
|
||||
"rejection.reason": "Amount too high"
|
||||
headers: # (10)
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
|
||||
#From the Consumer perspective, when shooting a request in the integration test:
|
||||
#
|
||||
#(1) - If the consumer sends a request
|
||||
#(2) - With the "PUT" method
|
||||
#(3) - to the URL "/fraudcheck"
|
||||
#(4) - with the JSON body that
|
||||
# * has a field `clientId`
|
||||
# * has a field `loanAmount` that is equal to `99999`
|
||||
#(5) - with header `Content-Type` equal to `application/json`
|
||||
#(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}`
|
||||
#(7) - then the response will be sent with
|
||||
#(8) - status equal `200`
|
||||
#(9) - and JSON body equal to
|
||||
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
|
||||
#(10) - with header `Content-Type` equal to `application/json`
|
||||
#
|
||||
#From the Producer perspective, in the autogenerated producer-side test:
|
||||
#
|
||||
#(1) - A request will be sent to the producer
|
||||
#(2) - With the "PUT" method
|
||||
#(3) - to the URL "/fraudcheck"
|
||||
#(4) - with the JSON body that
|
||||
# * has a field `clientId` `1234567890`
|
||||
# * has a field `loanAmount` that is equal to `99999`
|
||||
#(5) - with header `Content-Type` equal to `application/json`
|
||||
#(7) - then the test will assert if the response has been sent with
|
||||
#(8) - status equal `200`
|
||||
#(9) - and JSON body equal to
|
||||
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
|
||||
#(10) - with header `Content-Type` equal to `application/json;charset=UTF-8`</pre><p>
|
||||
</p><p>The YML contract is quite straight-forward. However when you take a look at the Contract
|
||||
written using a statically typed Groovy DSL - you might wonder what the
|
||||
<code class="literal">value(client(…​), server(…​))</code> parts are. By using this notation, Spring Cloud
|
||||
Contract lets you define parts of a JSON block, a URL, etc., which are dynamic. In case
|
||||
of an identifier or a timestamp, you need not hardcode a value. You want to allow some
|
||||
different ranges of values. To enable ranges of values, you can set regular expressions
|
||||
@@ -298,8 +409,8 @@ First, add the <code class="literal">Spring Cloud Contract</code> BOM.</p><pre c
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>Since the plugin was added, you get the <code class="literal">Spring Cloud Contract Verifier</code> features which,
|
||||
from the provided contracts:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">generate and run tests</li><li class="listitem">produce and install stubs</li></ul></div><p>You do not want to generate tests since you, as the consumer, want only to play with the
|
||||
stubs. You need to skip the test generation and execution. When you execute:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> local-http-server-repo
|
||||
./mvnw clean install -DskipTests</pre><p>In the logs, you see something like this:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<span class="hl-number">1.0</span>.<span class="hl-number">0.</span>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
||||
stubs. You need to skip the test generation and execution. When you execute:</p><pre class="programlisting">$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> local-http-server-repo
|
||||
$ ./mvnw clean install -DskipTests</pre><p>In the logs, you see something like this:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<span class="hl-number">1.0</span>.<span class="hl-number">0.</span>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
||||
[INFO] Building jar: /some/path/http-server/target/http-server-<span class="hl-number">0.0</span>.<span class="hl-number">1</span>-SNAPSHOT-stubs.jar
|
||||
[INFO]
|
||||
[INFO] --- maven-jar-plugin:<span class="hl-number">2.6</span>:jar (default-jar) @ http-server ---
|
||||
@@ -349,8 +460,8 @@ you wish.</p><p>Once you are satisfied with the results and the test passes, pub
|
||||
the server side. Currently, the consumer side work is done.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_side_fraud_detection_server" href="#_producer_side_fraud_detection_server"></a>2.4.3 Producer side (Fraud Detection server)</h3></div></div></div><p>As a developer of the Fraud Detection server (a server to the Loan Issuance service):</p><p><span class="strong"><strong>Create an initial implementation.</strong></span></p><p>As a reminder, you can see the initial implementation here:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RequestMapping(value = "/fraudcheck", method = PUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<em><span class="hl-annotation" style="color: gray">@RequestBody</span></em> FraudCheck fraudCheck) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
|
||||
}</pre><p><span class="strong"><strong>Take over the pull request.</strong></span></p><pre class="programlisting">git checkout -b contract-change-pr master
|
||||
git pull https://your-git-server.com/server-side-fork.git contract-change-pr</pre><p>You must add the dependencies needed by the autogenerated tests:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
}</pre><p><span class="strong"><strong>Take over the pull request.</strong></span></p><pre class="programlisting">$ git checkout -b contract-change-pr master
|
||||
$ git pull https://your-git-server.com/server-side-fork.git contract-change-pr</pre><p>You must add the dependencies needed by the autogenerated tests:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-contract-verifier<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
@@ -420,8 +531,9 @@ like this:</p><pre class="programlisting"><em><span class="hl-annotation" style=
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['fraudCheckStatus']"</span>).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[A-Z]{5}"</span>);
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['rejection.reason']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>);
|
||||
}</pre><p>As you can see, all the <code class="literal">producer()</code> parts of the Contract that were present in the
|
||||
<code class="literal">value(consumer(…​), producer(…​))</code> blocks got injected into the test.</p><p>Note that, on the producer side, you are also doing TDD. The expectations are expressed
|
||||
}</pre><p>If you used the Groovy DSL, you can see, all the <code class="literal">producer()</code> parts of the Contract that were present in the
|
||||
<code class="literal">value(consumer(…​), producer(…​))</code> blocks got injected into the test.
|
||||
In case of using YAML, the same applied for the <code class="literal">matchers</code> sections of the <code class="literal">response</code>.</p><p>Note that, on the producer side, you are also doing TDD. The expectations are expressed
|
||||
in the form of a test. This test sends a request to our own application with the URL,
|
||||
headers, and body defined in the contract. It also is expecting precisely defined values
|
||||
in the response. In other words, you have the <code class="literal">red</code> part of <code class="literal">red</code>, <code class="literal">green</code>, and
|
||||
@@ -434,11 +546,11 @@ implementation:</p><pre class="programlisting"><em><span class="hl-annotation" s
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
|
||||
}</pre><p>When you execute <code class="literal">./mvnw clean install</code> again, the tests pass. Since the <code class="literal">Spring Cloud
|
||||
Contract Verifier</code> plugin adds the tests to the <code class="literal">generated-test-sources</code>, you can
|
||||
actually run those tests from your IDE.</p><p><span class="strong"><strong>Deploy your app.</strong></span></p><p>Once you finish your work, you can deploy your change. First, merge the branch:</p><pre class="programlisting">git checkout master
|
||||
git merge --no-ff contract-change-pr
|
||||
git push origin master</pre><p>Your CI might run something like <code class="literal">./mvnw clean deploy</code>, which would publish both the
|
||||
application and the stub artifacts.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_side_loan_issuance_final_step" href="#_consumer_side_loan_issuance_final_step"></a>2.4.4 Consumer Side (Loan Issuance) Final Step</h3></div></div></div><p>As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):</p><p><span class="strong"><strong>Merge branch to master.</strong></span></p><pre class="programlisting">git checkout master
|
||||
git merge --no-ff contract-change-pr</pre><p><span class="strong"><strong>Work online.</strong></span></p><p>Now you can disable the offline work for Spring Cloud Contract Stub Runner and indicate
|
||||
actually run those tests from your IDE.</p><p><span class="strong"><strong>Deploy your app.</strong></span></p><p>Once you finish your work, you can deploy your change. First, merge the branch:</p><pre class="programlisting">$ git checkout master
|
||||
$ git merge --no-ff contract-change-pr
|
||||
$ git push origin master</pre><p>Your CI might run something like <code class="literal">./mvnw clean deploy</code>, which would publish both the
|
||||
application and the stub artifacts.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_side_loan_issuance_final_step" href="#_consumer_side_loan_issuance_final_step"></a>2.4.4 Consumer Side (Loan Issuance) Final Step</h3></div></div></div><p>As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):</p><p><span class="strong"><strong>Merge branch to master.</strong></span></p><pre class="programlisting">$ git checkout master
|
||||
$ git merge --no-ff contract-change-pr</pre><p><span class="strong"><strong>Work online.</strong></span></p><p>Now you can disable the offline work for Spring Cloud Contract Stub Runner and indicate
|
||||
where the repository with your stubs is located. At this moment the stubs of the server
|
||||
side are automatically downloaded from Nexus/Artifactory. You can set the value of
|
||||
<code class="literal">stubsMode</code> to <code class="literal">REMOTE</code>. The following code shows an example of
|
||||
|
||||
@@ -35,7 +35,8 @@ message is triggered by a component inside the application (for example, schedu
|
||||
meanings for different messaging implementations. For <span class="strong"><strong>Stream</strong></span> and <span class="strong"><strong>Integration</strong></span> it is
|
||||
first resolved as a <code class="literal">destination</code> of a channel. Then, if there is no such <code class="literal">destination</code>
|
||||
it is resolved as a channel name. For <span class="strong"><strong>Camel</strong></span>, that’s a certain component (for example,
|
||||
<code class="literal">jms</code>).</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_1_no_input_message" href="#_scenario_1_no_input_message"></a>5.3.1 Scenario 1: No Input Message</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><pre class="programlisting">def contractDsl = Contract.make {
|
||||
<code class="literal">jms</code>).</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_1_no_input_message" href="#_scenario_1_no_input_message"></a>5.3.1 Scenario 1: No Input Message</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">def contractDsl = Contract.make {
|
||||
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
|
||||
input {
|
||||
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>)
|
||||
@@ -48,7 +49,19 @@ it is resolved as a channel name. For <span class="strong"><strong>Camel</strong
|
||||
messagingContentType(applicationJson())
|
||||
}
|
||||
}
|
||||
}</pre><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">label: some_label
|
||||
input:
|
||||
triggeredBy: bookReturnedTriggered
|
||||
outputMessage:
|
||||
sentTo: activemq:output
|
||||
body:
|
||||
bookName: foo
|
||||
headers:
|
||||
BOOK-NAME: foo
|
||||
contentType: application/json</pre><p>
|
||||
</p><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
|
||||
bookReturnedTriggered();
|
||||
|
||||
@@ -75,7 +88,8 @@ it is resolved as a channel name. For <span class="strong"><strong>Camel</strong
|
||||
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bookName"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>)
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_2_output_triggered_by_input" href="#_scenario_2_output_triggered_by_input"></a>5.3.2 Scenario 2: Output Triggered by Input</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><pre class="programlisting">def contractDsl = Contract.make {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_2_output_triggered_by_input" href="#_scenario_2_output_triggered_by_input"></a>5.3.2 Scenario 2: Output Triggered by Input</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">def contractDsl = Contract.make {
|
||||
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
|
||||
input {
|
||||
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>)
|
||||
@@ -95,7 +109,22 @@ it is resolved as a channel name. For <span class="strong"><strong>Camel</strong
|
||||
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>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">label: some_label
|
||||
input:
|
||||
messageFrom: jms:input
|
||||
messageBody:
|
||||
bookName: 'foo'
|
||||
messageHeaders:
|
||||
sample: header
|
||||
outputMessage:
|
||||
sentTo: jms:output
|
||||
body:
|
||||
bookName: foo
|
||||
headers:
|
||||
BOOK-NAME: foo</pre><p>
|
||||
</p><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>bookName\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span>
|
||||
@@ -130,7 +159,8 @@ then:
|
||||
and:
|
||||
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
|
||||
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bookName"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_3_no_output_message" href="#_scenario_3_no_output_message"></a>5.3.3 Scenario 3: No Output Message</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><pre class="programlisting">def contractDsl = Contract.make {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_3_no_output_message" href="#_scenario_3_no_output_message"></a>5.3.3 Scenario 3: No Output Message</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><p><b>Groovy DSL. </b>
|
||||
</p><pre class="programlisting">def contractDsl = Contract.make {
|
||||
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
|
||||
input {
|
||||
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:delete'</span>)
|
||||
@@ -142,7 +172,17 @@ and:
|
||||
}
|
||||
assertThat(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookWasDeleted()'</span>)
|
||||
}
|
||||
}</pre><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
</p><pre class="programlisting">label: some_label
|
||||
input:
|
||||
messageFrom: jms:delete
|
||||
messageBody:
|
||||
bookName: 'foo'
|
||||
messageHeaders:
|
||||
sample: header
|
||||
assertThat: bookWasDeleted()</pre><p>
|
||||
</p><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>bookName\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>4. Spring Cloud Contract Verifier Setup</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_faq.html" title="3. Spring Cloud Contract FAQ"><link rel="next" href="multi__spring_cloud_contract_verifier_messaging.html" title="5. Spring Cloud Contract Verifier 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">4. Spring Cloud Contract Verifier Setup</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_faq.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_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_verifier_setup" href="#_spring_cloud_contract_verifier_setup"></a>4. Spring Cloud Contract Verifier Setup</h1></div></div></div><p>You can set up Spring Cloud Contract Verifier in either of two ways</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#gradle-project" title="4.1 Gradle Project">As a Gradle project</a></li><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#maven-project" title="4.2 Maven Project">As a Maven project</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="gradle-project" href="#gradle-project"></a>4.1 Gradle Project</h2></div></div></div><p>To learn how to set up the Gradle project for Spring Cloud Contract Verifier, read the
|
||||
<title>4. Spring Cloud Contract Verifier Setup</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_faq.html" title="3. Spring Cloud Contract FAQ"><link rel="next" href="multi__spring_cloud_contract_verifier_messaging.html" title="5. Spring Cloud Contract Verifier 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">4. Spring Cloud Contract Verifier Setup</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_faq.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_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_verifier_setup" href="#_spring_cloud_contract_verifier_setup"></a>4. Spring Cloud Contract Verifier Setup</h1></div></div></div><p>You can set up Spring Cloud Contract Verifier in the following ways:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#gradle-project" title="4.1 Gradle Project">As a Gradle project</a></li><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#maven-project" title="4.2 Maven Project">As a Maven project</a></li><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#docker-project" title="4.5 Docker Project">As a Docker project</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="gradle-project" href="#gradle-project"></a>4.1 Gradle Project</h2></div></div></div><p>To learn how to set up the Gradle project for Spring Cloud Contract Verifier, read the
|
||||
following sections:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-prerequisites" title="4.1.1 Prerequisites">Section 4.1.1, “Prerequisites”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-add-gradle-plugin" title="4.1.2 Add Gradle Plugin with Dependencies">Section 4.1.2, “Add Gradle Plugin with Dependencies”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-and-rest-assured" title="4.1.3 Gradle and Rest Assured 2.0">Section 4.1.3, “Gradle and Rest Assured 2.0”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-snapshot-versions" title="4.1.4 Snapshot Versions for Gradle">Section 4.1.4, “Snapshot Versions for Gradle”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-add-stubs" title="4.1.5 Add stubs">Section 4.1.5, “Add stubs”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-default-setup" title="4.1.7 Default Setup">Section 4.1.7, “Default Setup”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-configure-plugin" title="4.1.8 Configure Plugin">Section 4.1.8, “Configure Plugin”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-configuration-options" title="4.1.9 Configuration Options">Section 4.1.9, “Configuration Options”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-single-base-class" title="4.1.10 Single Base Class for All Tests">Section 4.1.10, “Single Base Class for All Tests”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-different-base-classes" title="4.1.11 Different Base Classes for Contracts">Section 4.1.11, “Different Base Classes for Contracts”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-invoking-generated-tests" title="4.1.12 Invoking Generated Tests">Section 4.1.12, “Invoking Generated Tests”</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-consumer" title="4.1.13 Spring Cloud Contract Verifier on the Consumer Side">Section 4.1.13, “Spring Cloud Contract Verifier on the Consumer Side”</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-prerequisites" href="#gradle-prerequisites"></a>4.1.1 Prerequisites</h3></div></div></div><p>In order to use Spring Cloud Contract Verifier with WireMock, you muse use either a
|
||||
Gradle or a Maven plugin.</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 you want to use Spock in your projects, you must add separately the
|
||||
<code class="literal">spock-core</code> and <code class="literal">spock-spring</code> modules. Check <a class="link" href="http://spockframework.github.io/" target="_top">Spock
|
||||
@@ -552,10 +552,82 @@ optional, they will not get downloaded.</p><p><span class="strong"><strong>Creat
|
||||
For example, you might decide to have no dependencies at all.</p><p><span class="strong"><strong>Exclude dependencies on the consumer side</strong></span></p><p>As a consumer, if you add the stub dependency to your classpath, you can explicitly
|
||||
exclude the unwanted dependencies.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_scenarios" href="#_scenarios"></a>4.4 Scenarios</h2></div></div></div><p>You can handle scenarios with Spring Cloud Contract Verifier. All you need to do is to
|
||||
stick to the proper naming convention while creating your contracts. The convention
|
||||
requires including an order number followed by an underscore, as shown in this example:</p><pre class="screen">my_contracts_dir\
|
||||
requires including an order number followed by an underscore. This will work regardles
|
||||
of whether you’re working with YAML or Groovy. Example:</p><pre class="screen">my_contracts_dir\
|
||||
scenario1\
|
||||
1_login.groovy
|
||||
2_showCart.groovy
|
||||
3_logout.groovy</pre><p>Such a tree causes Spring Cloud Contract Verifier to generate WireMock’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…​</li><li class="listitem">showCart marked as <code class="literal">Step1</code> pointing to…​</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><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_faq.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Spring Cloud Contract FAQ </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"> 5. Spring Cloud Contract Verifier Messaging</td></tr></table></div></body></html>
|
||||
<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.5 Docker Project</h2></div></div></div><p>We’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.5.1 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’s good to
|
||||
explain the basic terms behind Spring Cloud Contract packaging defaults.</p><p>Part of the following definitions were taken from the <a class="link" href="https://maven.apache.org/glossary.html" target="_top">Maven Glossary</a></p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">Project</code>: Maven thinks in terms of projects. Everything that you
|
||||
will build are projects. Those projects follow a well defined
|
||||
“Project Object Model”. Projects can depend on other projects,
|
||||
in which case the latter are called “dependencies”. A project may
|
||||
consistent of several subprojects, however these subprojects are still
|
||||
treated equally as projects.</li><li class="listitem"><code class="literal">Artifact</code>: An artifact is something that is either produced or used
|
||||
by a project. Examples of artifacts produced by Maven for a project
|
||||
include: JARs, source and binary distributions. Each artifact
|
||||
is uniquely identified by a group id and an artifact ID which is
|
||||
unique within a group.</li><li class="listitem"><code class="literal">JAR</code>: JAR stands for Java ARchive. It’s a format based on
|
||||
the ZIP file format. Spring Cloud Contract packages the contracts and generated
|
||||
stubs in a JAR file.</li><li class="listitem"><code class="literal">GroupId</code>: A group ID is a universally unique identifier for a project.
|
||||
While this is often just the project name (eg. commons-collections),
|
||||
it is helpful to use a fully-qualified package name to distinguish it
|
||||
from other projects with a similar name (eg. org.apache.maven).
|
||||
Typically, when published to the Artifact Manager, the <code class="literal">GroupId</code> will get
|
||||
slash separated and form part of the URL. E.g. for group id <code class="literal">com.example</code>
|
||||
and artifact id <code class="literal">application</code> would be <code class="literal">/com/example/application/</code>.</li><li class="listitem"><code class="literal">Classifier</code>: The Maven dependency notation looks as follows:
|
||||
<code class="literal">groupId:artifactId:version:classifier</code>. The classifier is additional suffix
|
||||
passed to the dependency. E.g. <code class="literal">stubs</code>, <code class="literal">sources</code>. The same dependency
|
||||
e.g. <code class="literal">com.example:application</code> can produce multiple artifacts that
|
||||
differ from each other with the classifier.</li><li class="listitem"><code class="literal">Artifact manager</code>: When you generate binaries / sources / packages, you would
|
||||
like them to be available for others to download / reference or reuse. In case
|
||||
of the JVM world those artifacts would be JARs, for Ruby these are gems
|
||||
and for Docker those would be Docker images. You can store those artifacts
|
||||
in a manager. Examples of such managers can be <a class="link" href="https://jfrog.com/artifactory/" target="_top">Artifactory</a>
|
||||
or <a class="link" href="http://www.sonatype.org/nexus/" target="_top">Nexus</a>.</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_it_works_2" href="#_how_it_works_2"></a>4.5.2 How it works</h3></div></div></div><p>The image searches for contracts under the <code class="literal">/contracts</code> folder.
|
||||
The output from running the tests will be available under
|
||||
<code class="literal">/spring-cloud-contract/build</code> folder (it’s useful for debugging
|
||||
purposes).</p><p>It’s enough for you to mount your contracts, pass the environment variables
|
||||
and the image will:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">generate the contract tests</li><li class="listitem">execute the tests against the provided URL</li><li class="listitem">generate the <a class="link" href="http://wiremock.org" target="_top">WireMock</a> stubs</li><li class="listitem">(optional - turned on by default) publish the stubs to a Artifact Manager</li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_environment_variables" href="#_environment_variables"></a>Environment Variables</h4></div></div></div><p>The Docker image requires some environment variables to point to
|
||||
your running application, to the Artifact manager instance etc.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">PROJECT_GROUP</code> - your project’s group id. Defaults to <code class="literal">com.example</code>.</li><li class="listitem"><code class="literal">PROJECT_VERSION</code> - your project’s version. Defaults to <code class="literal">0.0.1-SNAPSHOT</code></li><li class="listitem"><code class="literal">PROJECT_NAME</code> - artifact id. Defaults to <code class="literal">example</code></li><li class="listitem"><code class="literal">REPO_WITH_BINARIES_URL</code> - URL of your Artifact Manager. Defaults to <code class="literal"><a class="link" href="http://localhost:8081/artifactory/libs-release-local" target="_top">http://localhost:8081/artifactory/libs-release-local</a></code>
|
||||
which is the default URL of <a class="link" href="https://jfrog.com/artifactory/" target="_top">Artifactory</a> running locally</li><li class="listitem"><code class="literal">REPO_WITH_BINARIES_USERNAME</code> - (optional) username when the Artifact Manager is secured</li><li class="listitem"><code class="literal">REPO_WITH_BINARIES_PASSWORD</code> - (optional) password when the Artifact Manager is secured</li><li class="listitem"><code class="literal">PUBLISH_ARTIFACTS</code> - if set to <code class="literal">true</code> then will publish artifact to binary storage. Defaults to <code class="literal">true</code>.</li></ul></div><p>These environment variables are used when tests are executed:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">APPLICATION_BASE_URL</code> - url against which tests should be executed.
|
||||
Remember that it has to be accessible from the Docker container (e.g. <code class="literal">localhost</code>
|
||||
will not work)</li><li class="listitem"><code class="literal">APPLICATION_USERNAME</code> - (optional) username for basic authentication to your application</li><li class="listitem"><code class="literal">APPLICATION_PASSWORD</code> - (optional) password for basic authentication to your application</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example_of_usage" href="#_example_of_usage"></a>4.5.3 Example of usage</h3></div></div></div><p>Let’s take a look at a simple MVC application</p><pre class="programlisting">$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
|
||||
$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> bookstore</pre><p>The contracts are available under <code class="literal">/contracts</code> folder.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="docker-server-side" href="#docker-server-side"></a>4.5.4 Server side (nodejs)</h3></div></div></div><p>Since we want to run tests, we could just execute:</p><pre class="programlisting">$ npm <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span></pre><p>however, for learning purposes, let’s split it into pieces:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Stop docker infra (nodejs, artifactory)</span>
|
||||
$ ./stop_infra.sh
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Start docker infra (nodejs, artifactory)</span>
|
||||
$ ./setup_infra.sh
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Kill & Run app</span>
|
||||
$ pkill -f <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"node app"</span>
|
||||
$ nohup node app &
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Prepare environment variables</span>
|
||||
$ SC_CONTRACT_DOCKER_VERSION=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"..."</span>
|
||||
$ APP_IP=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"192.168.0.100"</span>
|
||||
$ APP_PORT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"3000"</span>
|
||||
$ ARTIFACTORY_PORT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"8081"</span>
|
||||
$ APPLICATION_BASE_URL=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://${APP_IP}:${APP_PORT}"</span>
|
||||
$ ARTIFACTORY_URL=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://${APP_IP}:${ARTIFACTORY_PORT}/artifactory/libs-release-local"</span>
|
||||
$ CURRENT_DIR=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$( pwd )"</span>
|
||||
$ CURRENT_FOLDER_NAME=${PWD<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">##*/}</span>
|
||||
$ PROJECT_VERSION=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"0.0.1.RELEASE"</span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Execute contract tests</span>
|
||||
$ docker run --rm -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"APPLICATION_BASE_URL=${APPLICATION_BASE_URL}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PUBLISH_ARTIFACTS=true"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PROJECT_NAME=${CURRENT_FOLDER_NAME}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"REPO_WITH_BINARIES_URL=${ARTIFACTORY_URL}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PROJECT_VERSION=${PROJECT_VERSION}"</span> -v <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${CURRENT_DIR}/contracts/:/contracts:ro"</span> -v <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${CURRENT_DIR}/node_modules/spring-cloud-contract/output:/spring-cloud-contract-output/"</span> springcloud/spring-cloud-contract:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${SC_CONTRACT_DOCKER_VERSION}"</span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Kill app</span>
|
||||
$ pkill -f <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"node app"</span></pre><p>What will happen is that via bash scripts:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">infrastructure will be set up (MongoDb, Artifactory).
|
||||
In real life scenario you would just run the NodeJS application
|
||||
with mocked database. In this example we want to show how we can
|
||||
benefit from Spring Cloud Contract in no time.</li><li class="listitem"><p class="simpara">due to those constraints the contracts also represent the
|
||||
stateful situation</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">first request is a <code class="literal">POST</code> that causes data to get inserted to the database</li><li class="listitem">second request is a <code class="literal">GET</code> that returns a list of data with 1 previously inserted element</li></ul></div></li><li class="listitem">the NodeJS application will be started (on port <code class="literal">3000</code>)</li><li class="listitem"><p class="simpara">contract tests will be generated via Docker and tests
|
||||
will be executed against the running application</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">the contracts will be taken from <code class="literal">/contracts</code> folder.</li><li class="listitem">the output of the test execution is available under
|
||||
<code class="literal">node_modules/spring-cloud-contract/output</code>.</li></ul></div></li><li class="listitem">the stubs will be uploaded to Artifactory. You can check them out
|
||||
under <a class="link" href="http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/" target="_top">http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/</a> .
|
||||
The stubs will be here <a class="link" href="http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar" target="_top">http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar</a>.</li></ul></div><p>To see how the client side looks like check out the <a class="xref" href="multi__spring_cloud_contract_stub_runner.html#stubrunner-docker" title="6.9 Stub Runner Docker">Section 6.9, “Stub Runner Docker”</a> section.</p></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_faq.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Spring Cloud Contract FAQ </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"> 5. Spring Cloud Contract Verifier Messaging</td></tr></table></div></body></html>
|
||||
@@ -152,12 +152,13 @@ Example:</p><pre class="programlisting"> <em><span class="hl-annotation" style=
|
||||
}
|
||||
};
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_generating_stubs_using_rest_docs" href="#_generating_stubs_using_rest_docs"></a>11.7 Generating Stubs using REST Docs</h2></div></div></div><p><a class="link" href="https://projects.spring.io/spring-restdocs" target="_top">Spring REST Docs</a> can be used to generate
|
||||
documentation (for example in Asciidoctor format) for an HTTP API with Spring MockMvc or
|
||||
documentation (for example in Asciidoctor format) for an HTTP API with Spring MockMvc
|
||||
or <code class="literal">WebTestClient</code> or
|
||||
Rest Assured. At the same time that you generate documentation for your API, you can also
|
||||
generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your
|
||||
normal REST Docs test cases and use <code class="literal">@AutoConfigureRestDocs</code> to have stubs be
|
||||
automatically generated in the REST Docs output directory. The following code shows an
|
||||
example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
example using <code class="literal">MockMvc</code>:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureRestDocs(outputDir = "target/snippets")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureMockMvc</span></em>
|
||||
@@ -173,32 +174,49 @@ example:</p><pre class="programlisting"><em><span class="hl-annotation" style="c
|
||||
.andDo(document(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"resource"</span>));
|
||||
}
|
||||
}</pre><p>This test generates a WireMock stub at "target/snippets/stubs/resource.json". It matches
|
||||
all GET requests to the "/resource" path.</p><p>Without any additional configuration, this tests creates a stub with a request matcher
|
||||
all GET requests to the "/resource" path. The same example with <code class="literal">WebTestClient</code> (used
|
||||
for testing Spring WebFlux applications) would look like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureRestDocs(outputDir = "target/snippets")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureWebTestClient</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> WebTestClient client;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
client.get().uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>).exchange()
|
||||
.expectBody(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span>)
|
||||
.consumeWith(document(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"resource"</span>));
|
||||
}
|
||||
}</pre><p>Without any additional configuration, these tests create a stub with a request matcher
|
||||
for the HTTP method and all headers except "host" and "content-length". To match the
|
||||
request more precisely (for example, to match the body of a POST or PUT), we need to
|
||||
explicitly create a request matcher. Doing so has two effects:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Creating a stub that matches only in the way you specify.</li><li class="listitem">Asserting that the request in the test case also matches the same conditions.</li></ul></div><p>The main entry point for this feature is <code class="literal">WireMockRestDocs.verify()</code>, which can be used
|
||||
as a substitute for the <code class="literal">document()</code> convenience method, as shown in the following
|
||||
example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootTest</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureRestDocs(outputDir = "target/snippets")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@AutoConfigureMockMvc</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ApplicationTests {
|
||||
example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocs.verify;</pre><pre class="screen">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureRestDocs(outputDir = "target/snippets")
|
||||
@AutoConfigureMockMvc
|
||||
public class ApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MockMvc mockMvc;
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
mockMvc.perform(post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>)
|
||||
.content(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"id\":\"123456\",\"message\":\"Hello World\"}"</span>))
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
mockMvc.perform(post("/resource")
|
||||
.content("{\"id\":\"123456\",\"message\":\"Hello World\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(verify().jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.id"</span>)
|
||||
.stub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"resource"</span>));
|
||||
.andDo(verify().jsonPath("$.id")
|
||||
.stub("resource"));
|
||||
}
|
||||
}</pre><p>This contract specifies that any valid POST with an "id" field receives the response
|
||||
defined in this test. You can chain together calls to <code class="literal">.jsonPath()</code> to add additional
|
||||
matchers. If JSON Path is unfamiliar, The <a class="link" href="https://github.com/jayway/JsonPath" target="_top">JayWay
|
||||
documentation</a> can help you get up to speed.</p><p>Instead of the <code class="literal">jsonPath</code> and <code class="literal">contentType</code> convenience methods, you can also use the
|
||||
documentation</a> can help you get up to speed. The <code class="literal">WebTestClient</code> version of this test
|
||||
has a similar <code class="literal">verify()</code> static helper that you insert in the same place.</p><p>Instead of the <code class="literal">jsonPath</code> and <code class="literal">contentType</code> convenience methods, you can also use the
|
||||
WireMock APIs to verify that the request matches the created stub, as shown in the
|
||||
following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Test</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
|
||||
@@ -5,19 +5,7 @@ such as YAML, RAML or PACT. In those cases, you still want to benefit from the a
|
||||
generation of tests and stubs. You can add your own implementation for generating both
|
||||
tests and stubs. Also, you can customize the way tests are generated (for example, you
|
||||
can generate tests for other languages) and the way stubs are generated (for example, you
|
||||
can generate stubs for other HTTP server implementations).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_contract_converter" href="#_custom_contract_converter"></a>10.1 Custom Contract Converter</h2></div></div></div><p>Assume that your contract is written in a YAML file as follows:</p><pre class="programlisting">request:
|
||||
url: /foo
|
||||
method: PUT
|
||||
headers:
|
||||
foo: bar
|
||||
body:
|
||||
foo: bar
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
foo2: bar
|
||||
body:
|
||||
foo2: bar</pre><p>The <code class="literal">ContractConverter</code> interface lets you register your own implementation of a contract
|
||||
can generate stubs for other HTTP server implementations).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_contract_converter" href="#_custom_contract_converter"></a>10.1 Custom Contract Converter</h2></div></div></div><p>The <code class="literal">ContractConverter</code> interface lets you register your own implementation of a contract
|
||||
structure converter. The following code listing shows the <code class="literal">ContractConverter</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.spec
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
@@ -58,87 +46,8 @@ structure converter. The following code listing shows the <code class="literal">
|
||||
}</pre><p>Your implementation must define the condition on which it should start the
|
||||
conversion. Also, you must define how to perform that conversion in both directions.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Once you create your implementation, you must create a
|
||||
<code class="literal">/META-INF/spring.factories</code> file in which you provide the fully qualified name of your
|
||||
implementation.</p></td></tr></table></div><p>The following example shows a typical <code class="literal">spring.factories</code> file:</p><pre class="screen"># Converters
|
||||
org.springframework.cloud.contract.spec.ContractConverter=\
|
||||
org.springframework.cloud.contract.verifier.converter.YamlContractConverter
|
||||
|
||||
# tag::extension[]
|
||||
org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockExtensions=\
|
||||
org.springframework.cloud.contract.verifier.dsl.wiremock.TestWireMockExtensions
|
||||
# end::extension[]</pre><p>The following example shows a typical YAML implementation that matches the preceding
|
||||
example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.verifier.converter
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.nio.file.Files
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> groovy.transform.CompileStatic
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.ContractConverter
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.Headers
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.yaml.snakeyaml.Yaml
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* Simple converter from and to a {@link YamlContract} to a collection of {@link Contract}
|
||||
*/</strong>
|
||||
<em><span class="hl-annotation" style="color: gray">@CompileStatic</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> YamlContractConverter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> ContractConverter<List<YamlContract>> {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">boolean</span> isAccepted(File file) {
|
||||
String name = file.getName()
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> name.endsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">".yml"</span>) || name.endsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">".yaml"</span>)
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Collection<Contract> convertFrom(File file) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
YamlContract yamlContract = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Yaml().loadAs(
|
||||
Files.newInputStream(file.toPath()), YamlContract.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> [Contract.make {
|
||||
request {
|
||||
method(yamlContract?.request?.method)
|
||||
url(yamlContract?.request?.url)
|
||||
headers {
|
||||
yamlContract?.request?.headers?.each { String key, Object value ->
|
||||
header(key, value)
|
||||
}
|
||||
}
|
||||
body(yamlContract?.request?.body)
|
||||
}
|
||||
response {
|
||||
status(yamlContract?.response?.status)
|
||||
headers {
|
||||
yamlContract?.response?.headers?.each { String key, Object value ->
|
||||
header(key, value)
|
||||
}
|
||||
}
|
||||
body(yamlContract?.response?.body)
|
||||
}
|
||||
}]
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (FileNotFoundException e) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> IllegalStateException(e)
|
||||
}
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> List<YamlContract> convertTo(Collection<Contract> contracts) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> contracts.collect { Contract contract ->
|
||||
YamlContract yamlContract = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> YamlContract()
|
||||
yamlContract.request.with {
|
||||
method = contract?.request?.method?.clientValue
|
||||
url = contract?.request?.url?.clientValue
|
||||
headers = (contract?.request?.headers as Headers)?.asStubSideMap()
|
||||
body = contract?.request?.body?.clientValue as Map
|
||||
}
|
||||
yamlContract.response.with {
|
||||
status = contract?.response?.status?.clientValue as Integer
|
||||
headers = (contract?.response?.headers as Headers)?.asStubSideMap()
|
||||
body = contract?.response?.body?.clientValue as Map
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> yamlContract
|
||||
}
|
||||
}
|
||||
}</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_converter" href="#_pact_converter"></a>10.1.1 Pact Converter</h3></div></div></div><p>Spring Cloud Contract includes support for <a class="link" href="https://docs.pact.io/" target="_top">Pact</a> representation of
|
||||
implementation.</p></td></tr></table></div><p>The following example shows a typical <code class="literal">spring.factories</code> file:</p><pre class="screen">org.springframework.cloud.contract.spec.ContractConverter=\
|
||||
org.springframework.cloud.contract.verifier.converter.YamlContractConverter</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_converter" href="#_pact_converter"></a>10.1.1 Pact Converter</h3></div></div></div><p>Spring Cloud Contract includes support for <a class="link" href="https://docs.pact.io/" target="_top">Pact</a> representation of
|
||||
contracts. Instead of using the Groovy DSL, you can use Pact files. In this section, we
|
||||
present how to add Pact support for your project.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_contract" href="#_pact_contract"></a>10.1.2 Pact Contract</h3></div></div></div><p>Consider following example of a Pact contract, which is a file under the
|
||||
<code class="literal">src/test/resources/contracts</code> folder.</p><pre class="programlisting">{
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Checkstyle Results</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -116,7 +116,7 @@ under the License.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.stubrunner.RemoteStubRunner.java">org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java</a>
|
||||
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.RunMojo.java">org/springframework/cloud/contract/maven/verifier/RunMojo.java</a>
|
||||
</td>
|
||||
<td>
|
||||
0
|
||||
@@ -144,7 +144,7 @@ under the License.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.RunMojo.java">org/springframework/cloud/contract/maven/verifier/RunMojo.java</a>
|
||||
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.stubrunner.RemoteStubRunner.java">org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java</a>
|
||||
</td>
|
||||
<td>
|
||||
0
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – </title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – </title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – spring-cloud-contract:convert</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – spring-cloud-contract:generateStubs</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – spring-cloud-contract:generateTests</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – spring-cloud-contract:help</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – </title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – CI Management</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Issue Management</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – </title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Project Licenses</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Plugin Documentation</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Project Plugin Management</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
@@ -413,7 +413,7 @@
|
||||
<tr class="a">
|
||||
<td>org.springframework.boot</td>
|
||||
<td><a class="externalLink" href="http://projects.spring.io/spring-boot/spring-boot-parent/spring-boot-tools/spring-boot-maven-plugin/">spring-boot-maven-plugin</a></td>
|
||||
<td>2.0.0.M7</td></tr>
|
||||
<td>2.0.0.BUILD-SNAPSHOT</td></tr>
|
||||
<tr class="b">
|
||||
<td>pl.project13.maven</td>
|
||||
<td><a class="externalLink" href="http://www.blog.project13.pl">git-commit-id-plugin</a></td>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Project Plugins</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Project Information</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Generated Reports</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Project Summary</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – spring-cloud-contract:run</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Sitemap</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Source Code Management</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – </title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – Project Team</title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-03
|
||||
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2018-01-25
|
||||
| Rendered using Apache Maven Fluido Skin 1.5
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180103" />
|
||||
<meta name="Date-Revision-yyyymmdd" content="20180125" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<title>Spring Cloud Contract Maven Plugin – </title>
|
||||
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
|
||||
@@ -146,7 +146,7 @@
|
||||
<div id="breadcrumbs">
|
||||
<ul class="breadcrumb">
|
||||
|
||||
<li id="publishDate">Last Published: 2018-01-03
|
||||
<li id="publishDate">Last Published: 2018-01-25
|
||||
<span class="divider">|</span>
|
||||
</li>
|
||||
<li id="projectVersion">Version: 2.0.0.BUILD-SNAPSHOT
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user