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;
|
||||
|
||||
Reference in New Issue
Block a user