Sync docs from master to gh-pages

This commit is contained in:
Marcin Grzejszczak
2019-01-01 11:58:52 +01:00
parent 9dd4f1380f
commit 0be1ee6ada
9 changed files with 788 additions and 316 deletions

View File

@@ -145,7 +145,7 @@ visible in your Groovy files. The following examples show how to test the depend
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1-SNAPSHOT"</span>)</pre><p class="secondary">
</p><pre class="programlisting">testCompile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1.BUILD-SNAPSHOT"</span>)</pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_test_a_dependency_in_the_plugins_dependencies" href="#_test_a_dependency_in_the_plugins_dependencies"></a>9.1.4&nbsp;Test a Dependency in the Plugin&#8217;s Dependencies</h3></div></div></div><p>Now, you must add the dependency for the plugin to reuse at runtime, as shown in the
following example:</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
@@ -172,7 +172,7 @@ following example:</p><p class="primary"><b>Maven.&nbsp;</b>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1-SNAPSHOT"</span></pre><p class="secondary">
</p><pre class="programlisting">classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1.BUILD-SNAPSHOT"</span></pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_referencing_classes_in_dsls" href="#_referencing_classes_in_dsls"></a>9.1.5&nbsp;Referencing classes in DSLs</h3></div></div></div><p>You can now reference your classes in your DSL, as shown in the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts.beer.rest
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.example.ConsumerUtils
@@ -214,4 +214,4 @@ then:
contentType(applicationJson())
}
}
}</pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_contract-dsl.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8.&nbsp;Contract DSL&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;10.&nbsp;Using the Pluggable Architecture</td></tr></table></div></body></html>
}</pre><div 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 can set the Spring Cloud Contract plugin up by setting <code class="literal">convertToYaml</code> to <code class="literal">true</code>. That way you will NOT have to add the dependency with the extended functionality to the consumer side, since the consumer side will be using YAML contracts instead of Groovy ones.</p></td></tr></table></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_contract-dsl.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8.&nbsp;Contract DSL&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;10.&nbsp;Using the Pluggable Architecture</td></tr></table></div></body></html>

View File

@@ -457,10 +457,95 @@ the `publish` task is executed
publish.dependsOn("publishStubsToScm")</pre><p>
</p><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Git project will be cloned to a temporary directory</li><li class="listitem">The SCM stub downloader will go to <code class="literal">META-INF/groupId/artifactId/version/contracts</code> folder
to find contracts. E.g. for <code class="literal">com.example:foo:1.0.0</code> the path would be
<code class="literal">META-INF/com.example/foo/1.0.0/contracts</code></li><li class="listitem">Tests will be generated from the contracts</li><li class="listitem">Stubs will be created from the contracts</li><li class="listitem">Once the tests pass, the stubs will be committed in the cloned repository</li><li class="listitem">Finally, a push will be done to that repo&#8217;s <code class="literal">origin</code></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository" href="#_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository"></a>Keeping contracts with the producer and stubs in an external repository</h4></div></div></div><p>It is also possible to keep the contracts in the producer repository, but keep the stubs in an external git repo.
<code class="literal">META-INF/com.example/foo/1.0.0/contracts</code></li><li class="listitem">Tests will be generated from the contracts</li><li class="listitem">Stubs will be created from the contracts</li><li class="listitem">Once the tests pass, the stubs will be committed in the cloned repository</li><li class="listitem">Finally, a push will be done to that repo&#8217;s <code class="literal">origin</code></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_with_contracts_stored_locally" href="#_producer_with_contracts_stored_locally"></a>3.6.3&nbsp;Producer with contracts stored locally</h3></div></div></div><p>Another option to use the SCM as the destination for stubs and contracts is to store the contracts locally, with the producer, and only push the contracts and the stubs to SCM. Below, you can find the setup required to achieve this using Maven and Gradle.</p><p><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- In the default configuration, we want to use the contracts stored locally --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMappings&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractPackageRegex&gt;</span>.*messaging.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractPackageRegex&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassFQN&gt;</span>com.example.BeerMessagingBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassFQN&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractPackageRegex&gt;</span>.*rest.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractPackageRegex&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassFQN&gt;</span>com.example.BeerRestBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassFQN&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMappings&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;basePackageForTests&gt;</span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/basePackageForTests&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;phase&gt;</span>package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/phase&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>pushStubsToScm<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- We want to pick contracts from a Git repository --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractsRepositoryUrl&gt;</span>git://file://${env.ROOT}/target/contract_empty_git/<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractsRepositoryUrl&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- Example of URL via git protocol --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!--&lt;contractsRepositoryUrl&gt;git://git@github.com:spring-cloud-samples/spring-cloud-contract-samples.git&lt;/contractsRepositoryUrl&gt;--&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- Example of URL via http protocol --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!--&lt;contractsRepositoryUrl&gt;git://https://github.com/spring-cloud-samples/spring-cloud-contract-samples.git&lt;/contractsRepositoryUrl&gt;--&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractDependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>${project.groupId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>${project.artifactId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractDependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- The mode can't be classpath --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractsMode&gt;</span>LOCAL<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractsMode&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>
</p><p><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">contracts {
// Base package for generated tests
basePackageForTests = "com.example"
baseClassMappings {
baseClassMapping(".*messaging.*", "com.example.BeerMessagingBase")
baseClassMapping(".*rest.*", "com.example.BeerRestBase")
}
}
/*
In this scenario we want to publish stubs to SCM whenever
the `publish` task is executed
*/
publishStubsToScm {
// We want to modify the default set up of the plugin when publish stubs to scm is called
customize {
// We want to pick contracts from a Git repository
contractDependency {
stringNotation = "${project.group}:${project.name}:${project.version}"
}
/*
We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts
*/
contractRepository {
repositoryUrl = "git://file://${System.getenv("ROOT")}/target/contract_empty_git/"
}
// The mode can't be classpath
contractsMode = "LOCAL"
}
}
publish.dependsOn("publishStubsToScm")
publishToMavenLocal.dependsOn("publishStubsToScm")</pre><p>
</p><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Contracts from the default <code class="literal">src/test/resources/contracts</code> directory will be picked</li><li class="listitem">Tests will be generated from the contracts</li><li class="listitem">Stubs will be created from the contracts</li><li class="listitem"><p class="simpara">Once the tests pass</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">Git project will be cloned to a temporary directory</li><li class="listitem">The stubs and contracts will be committed in the cloned repository</li></ul></div></li><li class="listitem">Finally, a push will be done to that repo&#8217;s <code class="literal">origin</code></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository" href="#_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository"></a>Keeping contracts with the producer and stubs in an external repository</h4></div></div></div><p>It is also possible to keep the contracts in the producer repository, but keep the stubs in an external git repo.
This is most useful when you want to use the base consumer-producer collaboration flow, but do not have a possibility to
use an artifact repository for storing the stubs.</p><p>In order to do that, use the usual producer setup, and then add the <code class="literal">pushStubsToScm</code> goal and set
<code class="literal">contractsRepositoryUrl</code> to the repository where you want to keep the stubs.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_2" href="#_consumer_2"></a>3.6.3&nbsp;Consumer</h3></div></div></div><p>On the consumer side when passing the <code class="literal">repositoryRoot</code> parameter,
<code class="literal">contractsRepositoryUrl</code> to the repository where you want to keep the stubs.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_2" href="#_consumer_2"></a>3.6.4&nbsp;Consumer</h3></div></div></div><p>On the consumer side when passing the <code class="literal">repositoryRoot</code> parameter,
either from the <code class="literal">@AutoConfigureStubRunner</code> annotation, the
JUnit rule, JUnit 5 extension or properties, it&#8217;s enough to pass the URL of the
SCM repository, prefixed with the protocol. For example</p><pre class="programlisting">@AutoConfigureStubRunner(

View File

@@ -638,6 +638,7 @@ First, add the <code class="literal">Spring Cloud Contract</code> BOM.</p><pre c
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;convertToYaml&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/convertToYaml&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>Since the plugin was added, you get the <code class="literal">Spring Cloud Contract Verifier</code> features which,
from the provided contracts:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">generate and run tests</li><li class="listitem">produce and install stubs</li></ul></div><p>You do not want to generate tests since you, as the consumer, want only to play with the
@@ -703,6 +704,7 @@ $ git pull https://your-git-server.com/server-side-fork.git contract-change-pr</
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;convertToYaml&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/convertToYaml&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This example uses "convention based" naming by setting the
<code class="literal">packageWithBaseClasses</code> property. Doing so means that the two last packages combine to

View File

@@ -144,7 +144,7 @@ closure to set it up.</li><li class="listitem"><span class="strong"><strong>cont
downloaded, the path defaults to <code class="literal">groupid/artifactid</code> where <code class="literal">groupid</code> is slash
separated. Otherwise, it scans contracts under the provided directory.</li><li class="listitem"><span class="strong"><strong>contractsMode</strong></span>: Specifies the mode of downloading contracts (whether the
JAR is available offline, remotely etc.)</li><li class="listitem"><span class="strong"><strong>deleteStubsAfterTest</strong></span>: If set to <code class="literal">false</code> will not remove any downloaded
contracts from temporary directories</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-single-base-class" href="#gradle-single-base-class"></a>4.1.10&nbsp;Single Base Class for All Tests</h3></div></div></div><p>When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base
contracts from temporary directories</li></ul></div><p>Below you can find a list of experimental features you can turn on via the plugin:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>convertToYaml</strong></span>: converts all DSLs to the declarative, YAML format. This can be extremely useful when you&#8217;re using external libraries in your Groovy DSLs. By turning this feature on (by setting it to <code class="literal">true</code>) you will not need to add the library dependency on the consumer side.</li><li class="listitem"><span class="strong"><strong>assertJsonSize</strong></span>: You can check the size of JSON arrays in the generated tests. This feature is disabled by default.</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-single-base-class" href="#gradle-single-base-class"></a>4.1.10&nbsp;Single Base Class for All Tests</h3></div></div></div><p>When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base
specification for all generated acceptance tests. In this class, you need to point to an
endpoint, which should be verified.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BaseMockMvcSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
@@ -231,6 +231,7 @@ following sections:</p><div class="itemizedlist"><ul class="itemizedlist" style=
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;convertToYaml&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/convertToYaml&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>You can read more in the
<a class="link" href="https://cloud.spring.io/spring-cloud-static/spring-cloud-contract/2.0.0.RELEASE/spring-cloud-contract-maven-plugin/" target="_top">Spring
@@ -388,7 +389,7 @@ the following options:</p><div class="itemizedlist"><ul class="itemizedlist" sty
Defaults to <code class="literal">groupid/artifactid</code> where <code class="literal">gropuid</code> is slash separated.</li><li class="listitem"><span class="strong"><strong>contractsMode</strong></span>: Picks the mode in which stubs will be found and registered</li><li class="listitem"><span class="strong"><strong>deleteStubsAfterTest</strong></span>: If set to <code class="literal">false</code> will not remove any downloaded
contracts from temporary directories</li><li class="listitem"><span class="strong"><strong>contractsRepositoryUrl</strong></span>: URL to a repo with the artifacts that have contracts. If it is not provided,
use the current Maven ones.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryUsername</strong></span>: The user name to be used to connect to the repo with contracts.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryPassword</strong></span>: The password to be used to connect to the repo with contracts.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryProxyHost</strong></span>: The proxy host to be used to connect to the repo with contracts.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryProxyPort</strong></span>: The proxy port to be used to connect to the repo with contracts.</li></ul></div><p>We cache only non-snapshot, explicitly provided versions (for example
<code class="literal">+</code> or <code class="literal">1.0.0.BUILD-SNAPSHOT</code> won&#8217;t get cached). By default, this feature is turned on.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-single-base" href="#maven-single-base"></a>4.2.8&nbsp;Single Base Class for All Tests</h3></div></div></div><p>When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base
<code class="literal">+</code> or <code class="literal">1.0.0.BUILD-SNAPSHOT</code> won&#8217;t get cached). By default, this feature is turned on.</p><p>Below you can find a list of experimental features you can turn on via the plugin:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>convertToYaml</strong></span>: converts all DSLs to the declarative, YAML format. This can be extremely useful when you&#8217;re using external libraries in your Groovy DSLs. By turning this feature on (by setting it to <code class="literal">true</code>) you will not need to add the library dependency on the consumer side.</li><li class="listitem"><span class="strong"><strong>assertJsonSize</strong></span>: You can check the size of JSON arrays in the generated tests. This feature is disabled by default.</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-single-base" href="#maven-single-base"></a>4.2.8&nbsp;Single Base Class for All Tests</h3></div></div></div><p>When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base
specification for all generated acceptance tests. In this class, you need to point to an
endpoint, which should be verified.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.mycompany.tests

File diff suppressed because one or more lines are too long

View File

@@ -656,80 +656,80 @@ use in your contracts, as shown in the following example:</p><pre class="program
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(values.collect({<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"^$it\$"</span>}).join(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"|"</span>))
}
Pattern onlyAlphaUnicode() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> ONLY_ALPHA_UNICODE
RegexProperty onlyAlphaUnicode() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(ONLY_ALPHA_UNICODE).asString()
}
Pattern alphaNumeric() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> ALPHA_NUMERIC
RegexProperty alphaNumeric() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(ALPHA_NUMERIC).asString()
}
Pattern number() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> NUMBER
RegexProperty number() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(NUMBER).asDouble()
}
Pattern positiveInt() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> POSITIVE_INT
RegexProperty positiveInt() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(POSITIVE_INT).asInteger()
}
Pattern anyBoolean() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> TRUE_OR_FALSE
RegexProperty anyBoolean() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(TRUE_OR_FALSE).asBooleanType()
}
Pattern anInteger() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> INTEGER
RegexProperty anInteger() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(INTEGER).asInteger()
}
Pattern aDouble() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> DOUBLE
RegexProperty aDouble() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(DOUBLE).asDouble()
}
Pattern ipAddress() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> IP_ADDRESS
RegexProperty ipAddress() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(IP_ADDRESS).asString()
}
Pattern hostname() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> HOSTNAME_PATTERN
RegexProperty hostname() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(HOSTNAME_PATTERN).asString()
}
Pattern email() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> EMAIL
RegexProperty email() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(EMAIL).asString()
}
Pattern url() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> URL
RegexProperty url() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(URL).asString()
}
Pattern httpsUrl() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> HTTPS_URL
RegexProperty httpsUrl() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(HTTPS_URL).asString()
}
Pattern uuid(){
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> UUID
RegexProperty uuid(){
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(UUID).asString()
}
Pattern isoDate() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> ANY_DATE
RegexProperty isoDate() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(ANY_DATE).asString()
}
Pattern isoDateTime() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> ANY_DATE_TIME
RegexProperty isoDateTime() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(ANY_DATE_TIME).asString()
}
Pattern isoTime() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> ANY_TIME
RegexProperty isoTime() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(ANY_TIME).asString()
}
Pattern iso8601WithOffset() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> ISO8601_WITH_OFFSET
RegexProperty iso8601WithOffset() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(ISO8601_WITH_OFFSET).asString()
}
Pattern nonEmpty() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> NON_EMPTY
RegexProperty nonEmpty() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(NON_EMPTY).asString()
}
Pattern nonBlank() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> NON_BLANK
RegexProperty nonBlank() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RegexProperty(NON_BLANK).asString()
}</pre><p>In your contract, you can use it as shown in the following example:</p><pre class="programlisting">Contract dslWithOptionalsInString = Contract.make {
priority <span class="hl-number">1</span>
request {
@@ -1109,7 +1109,7 @@ This section is present in the <code class="literal">response</code> or <code cl
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"><p class="title"><b>Groovy DSL</b></p><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">For the stubs(in tests on the Consumer&#8217;s side):</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 consumer&#8217;s request via the provided JSON Path must be
equal to the value provided in the contract.</li><li class="listitem"><code class="literal">byRegex(&#8230;&#8203;)</code>: The value taken from the consumer&#8217;s request via the provided JSON Path must
match the regex.</li><li class="listitem"><code class="literal">byDate()</code>: The value taken from the consumer&#8217;s request via the provided JSON Path must
match the regex. You can also pass the type of the expected matched value (e.g. <code class="literal">asString()</code>, <code class="literal">asLong()</code> etc.)</li><li class="listitem"><code class="literal">byDate()</code>: The value taken from the consumer&#8217;s request 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 consumer&#8217;s request via the provided JSON Path must
match the regex for an ISO DateTime value.</li><li class="listitem"><code class="literal">byTime()</code>: The value taken from the consumer&#8217;s request via the provided JSON Path must
match the regex for an ISO Time value.</li></ul></div></li><li class="listitem"><p class="simpara">For the verification(in generated tests on the Producer&#8217;s side):</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 producer&#8217;s response via the provided JSON Path must be
@@ -1119,7 +1119,7 @@ the regex for an ISO Date value.</li><li class="listitem"><code class="literal">
match the regex for an ISO DateTime value.</li><li class="listitem"><code class="literal">byTime()</code>: The value taken from the producer&#8217;s response via the provided JSON Path must match
the regex for an ISO Time value.</li><li class="listitem"><code class="literal">byType()</code>: The value taken from the producer&#8217;s response via the provided JSON Path needs to be
of the same type as the type defined in the body of the response in the contract.
<code class="literal">byType</code> can take a closure, in which you can set <code class="literal">minOccurrence</code> and <code class="literal">maxOccurrence</code>.
<code class="literal">byType</code> can take a closure, in which you can set <code class="literal">minOccurrence</code> and <code class="literal">maxOccurrence</code>. For the request side, you should use the closure to assert size of the collection.
That way, you can assert the size of the flattened collection. To check the size of an
unflattened collection, use a custom method with the <code class="literal">byCommand(&#8230;&#8203;)</code> testMatcher.</li><li class="listitem"><p class="simpara"><code class="literal">byCommand(&#8230;&#8203;)</code>: The value taken from the producer&#8217;s response via the provided JSON Path is
passed as an input to the custom method that you provide. For example,
@@ -1128,11 +1128,12 @@ JSON Path gets passed. The type of the object read from the JSON can be one of t
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><li class="listitem"><code class="literal">byNull()</code>: The value taken from the response via the provided JSON Path must be null</li></ul></div></li></ul></div><p><b>YAML.&nbsp;</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
value: bar
regexType: as_string</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><li class="listitem"><code class="literal">by_null</code></li></ul></div></li></ul></div><p>Consider the following example:</p><p><b>Groovy DSL.&nbsp;</b>
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><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></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><li class="listitem"><code class="literal">by_null</code></li></ul></div></li></ul></div><p>You can also define which type the regular expression corresponds to via the <code class="literal">regexType</code> field. Below you can find the allowed list of regular expression types:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">as_integer</li><li class="listitem">as_double</li><li class="listitem">as_float,</li><li class="listitem">as_long</li><li class="listitem">as_short</li><li class="listitem">as_boolean</li><li class="listitem">as_string</li></ul></div><p>Consider the following example:</p><p><b>Groovy DSL.&nbsp;</b>
</p><pre class="programlisting">Contract contractDsl = Contract.make {
request {
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
@@ -1152,12 +1153,12 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
]
])
bodyMatchers {
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byRegex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{3}"</span>))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byRegex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{3}"</span>).asInteger())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byEquality())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.alpha'</span>, byRegex(onlyAlphaUnicode()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.alpha'</span>, byRegex(onlyAlphaUnicode()).asString())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.alpha'</span>, byEquality())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.number'</span>, byRegex(number()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.aBoolean'</span>, byRegex(anyBoolean()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.number'</span>, byRegex(number()).asInteger())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.aBoolean'</span>, byRegex(anyBoolean()).asBooleanType())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.date'</span>, byDate())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.dateTime'</span>, byTimestamp())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.time'</span>, byTime())
@@ -1201,18 +1202,18 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
])
bodyMatchers {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// asserts the jsonpath value against manual regex</span>
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byRegex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{3}"</span>))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byRegex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{3}"</span>).asInteger())
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// asserts the jsonpath value against the provided value</span>
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.duck'</span>, byEquality())
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// asserts the jsonpath value against some default regex</span>
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.alpha'</span>, byRegex(onlyAlphaUnicode()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.alpha'</span>, byRegex(onlyAlphaUnicode()).asString())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.alpha'</span>, byEquality())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.number'</span>, byRegex(number()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.positiveInteger'</span>, byRegex(anInteger()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.negativeInteger'</span>, byRegex(anInteger()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.positiveDecimalNumber'</span>, byRegex(aDouble()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.negativeDecimalNumber'</span>, byRegex(aDouble()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.aBoolean'</span>, byRegex(anyBoolean()))
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.number'</span>, byRegex(number()).asInteger())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.positiveInteger'</span>, byRegex(anInteger()).asInteger())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.negativeInteger'</span>, byRegex(anInteger()).asInteger())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.positiveDecimalNumber'</span>, byRegex(aDouble()).asDouble())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.negativeDecimalNumber'</span>, byRegex(aDouble()).asDouble())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.aBoolean'</span>, byRegex(anyBoolean()).asBooleanType())
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// asserts vs inbuilt time related regex</span>
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.date'</span>, byDate())
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$.dateTime'</span>, byTimestamp())
@@ -1282,6 +1283,20 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
key:
"complex.key": 'foo'
nullValue: null
valueWithMin:
- 1
- 2
- 3
valueWithMax:
- 1
- 2
- 3
valueWithMinMax:
- 1
- 2
- 3
valueWithMinEmpty: []
valueWithMaxEmpty: []
matchers:
url:
regex: /get/[0-9]
@@ -1344,6 +1359,16 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
type: by_equality
- path: $.nullvalue
type: by_null
- path: $.valueWithMin
type: by_type
minOccurrence: 1
- path: $.valueWithMax
type: by_type
maxOccurrence: 3
- path: $.valueWithMinMax
type: by_type
minOccurrence: 1
maxOccurrence: 3
response:
status: 200
cookies:
@@ -1491,51 +1516,60 @@ 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">"$.['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">"$[?(@.['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'].['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">"$.['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">"$[?(@.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">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.valueWithMin.size() &gt;= 1)]"</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">"$[?(@.valueWithMax.size() &lt;= 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">"$[?(@.valueWithMinMax.size() &gt;= 1 &amp;&amp; @.valueWithMinMax.size() &lt;= 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">"$[?(@.valueWithOccurrence.size() &gt;= 4 &amp;&amp; @.valueWithOccurrence.size() &lt;= 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-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>aBoolean\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":true,\\"</span>valueWithMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithOccurrence\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3,4],\\"</span>number\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>duck\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":123,\\"</span>alpha\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>abc\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMin\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>time\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span><span class="hl-number">01</span>:<span class="hl-number">02</span>:<span class="hl-number">34</span>\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithTypeMatch\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>string\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",\\"</span>valueWithMinMax\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":[1,2,3],\\"</span>valueWithoutAMatcher\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"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">"transformers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response-template"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-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 and response that the
@@ -1876,11 +1910,16 @@ request:
url: /users/1
response:
status: 200
---
request:
method: POST
url: /users/2
response:
status: 200
---
request:
method: POST
url: /users/3
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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>Spring Cloud Contract</title>
<date>2018-12-12</date>
<date>2018-11-18</date>
</info>
<preface>
<title></title>
@@ -1082,6 +1082,7 @@ First, add the <literal>Spring Cloud Contract</literal> BOM.</simpara>
&lt;extensions&gt;true&lt;/extensions&gt;
&lt;configuration&gt;
&lt;packageWithBaseClasses&gt;com.example.fraud&lt;/packageWithBaseClasses&gt;
&lt;convertToYaml&gt;true&lt;/convertToYaml&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;</programlisting>
<simpara>Since the plugin was added, you get the <literal>Spring Cloud Contract Verifier</literal> features which,
@@ -1190,6 +1191,7 @@ $ git pull https://your-git-server.com/server-side-fork.git contract-change-pr</
&lt;extensions&gt;true&lt;/extensions&gt;
&lt;configuration&gt;
&lt;packageWithBaseClasses&gt;com.example.fraud&lt;/packageWithBaseClasses&gt;
&lt;convertToYaml&gt;true&lt;/convertToYaml&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;</programlisting>
<important>
@@ -2066,6 +2068,129 @@ to find contracts. E.g. for <literal>com.example:foo:1.0.0</literal> the path wo
<simpara>Finally, a push will be done to that repo&#8217;s <literal>origin</literal></simpara>
</listitem>
</itemizedlist>
</section>
<section xml:id="_producer_with_contracts_stored_locally">
<title>Producer with contracts stored locally</title>
<simpara>Another option to use the SCM as the destination for stubs and contracts is to store the contracts locally, with the producer, and only push the contracts and the stubs to SCM. Below, you can find the setup required to achieve this using Maven and Gradle.</simpara>
<formalpara>
<title>Maven</title>
<para>
<programlisting language="xml" linenumbering="unnumbered">&lt;plugin&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
&lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
&lt;extensions&gt;true&lt;/extensions&gt;
&lt;!-- In the default configuration, we want to use the contracts stored locally --&gt;
&lt;configuration&gt;
&lt;baseClassMappings&gt;
&lt;baseClassMapping&gt;
&lt;contractPackageRegex&gt;.*messaging.*&lt;/contractPackageRegex&gt;
&lt;baseClassFQN&gt;com.example.BeerMessagingBase&lt;/baseClassFQN&gt;
&lt;/baseClassMapping&gt;
&lt;baseClassMapping&gt;
&lt;contractPackageRegex&gt;.*rest.*&lt;/contractPackageRegex&gt;
&lt;baseClassFQN&gt;com.example.BeerRestBase&lt;/baseClassFQN&gt;
&lt;/baseClassMapping&gt;
&lt;/baseClassMappings&gt;
&lt;basePackageForTests&gt;com.example&lt;/basePackageForTests&gt;
&lt;/configuration&gt;
&lt;executions&gt;
&lt;execution&gt;
&lt;phase&gt;package&lt;/phase&gt;
&lt;goals&gt;
&lt;!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal --&gt;
&lt;goal&gt;pushStubsToScm&lt;/goal&gt;
&lt;/goals&gt;
&lt;configuration&gt;
&lt;!-- We want to pick contracts from a Git repository --&gt;
&lt;contractsRepositoryUrl&gt;git://file://${env.ROOT}/target/contract_empty_git/&lt;/contractsRepositoryUrl&gt;
&lt;!-- Example of URL via git protocol --&gt;
&lt;!--&lt;contractsRepositoryUrl&gt;git://git@github.com:spring-cloud-samples/spring-cloud-contract-samples.git&lt;/contractsRepositoryUrl&gt;--&gt;
&lt;!-- Example of URL via http protocol --&gt;
&lt;!--&lt;contractsRepositoryUrl&gt;git://https://github.com/spring-cloud-samples/spring-cloud-contract-samples.git&lt;/contractsRepositoryUrl&gt;--&gt;
&lt;!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts --&gt;
&lt;contractDependency&gt;
&lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
&lt;artifactId&gt;${project.artifactId}&lt;/artifactId&gt;
&lt;version&gt;${project.version}&lt;/version&gt;
&lt;/contractDependency&gt;
&lt;!-- The mode can't be classpath --&gt;
&lt;contractsMode&gt;LOCAL&lt;/contractsMode&gt;
&lt;/configuration&gt;
&lt;/execution&gt;
&lt;/executions&gt;
&lt;/plugin&gt;</programlisting>
</para>
</formalpara>
<formalpara>
<title>Gradle</title>
<para>
<programlisting language="xml" linenumbering="unnumbered">contracts {
// Base package for generated tests
basePackageForTests = "com.example"
baseClassMappings {
baseClassMapping(".*messaging.*", "com.example.BeerMessagingBase")
baseClassMapping(".*rest.*", "com.example.BeerRestBase")
}
}
/*
In this scenario we want to publish stubs to SCM whenever
the `publish` task is executed
*/
publishStubsToScm {
// We want to modify the default set up of the plugin when publish stubs to scm is called
customize {
// We want to pick contracts from a Git repository
contractDependency {
stringNotation = "${project.group}:${project.name}:${project.version}"
}
/*
We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts
*/
contractRepository {
repositoryUrl = "git://file://${System.getenv("ROOT")}/target/contract_empty_git/"
}
// The mode can't be classpath
contractsMode = "LOCAL"
}
}
publish.dependsOn("publishStubsToScm")
publishToMavenLocal.dependsOn("publishStubsToScm")</programlisting>
</para>
</formalpara>
<simpara>With such a setup:</simpara>
<itemizedlist>
<listitem>
<simpara>Contracts from the default <literal>src/test/resources/contracts</literal> directory will be picked</simpara>
</listitem>
<listitem>
<simpara>Tests will be generated from the contracts</simpara>
</listitem>
<listitem>
<simpara>Stubs will be created from the contracts</simpara>
</listitem>
<listitem>
<simpara>Once the tests pass</simpara>
<itemizedlist>
<listitem>
<simpara>Git project will be cloned to a temporary directory</simpara>
</listitem>
<listitem>
<simpara>The stubs and contracts will be committed in the cloned repository</simpara>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<simpara>Finally, a push will be done to that repo&#8217;s <literal>origin</literal></simpara>
</listitem>
</itemizedlist>
<section xml:id="_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository">
<title>Keeping contracts with the producer and stubs in an external repository</title>
<simpara>It is also possible to keep the contracts in the producer repository, but keep the stubs in an external git repo.
@@ -2644,6 +2769,15 @@ JAR is available offline, remotely etc.)</simpara>
contracts from temporary directories</simpara>
</listitem>
</itemizedlist>
<simpara>Below you can find a list of experimental features you can turn on via the plugin:</simpara>
<itemizedlist>
<listitem>
<simpara><emphasis role="strong">convertToYaml</emphasis>: converts all DSLs to the declarative, YAML format. This can be extremely useful when you&#8217;re using external libraries in your Groovy DSLs. By turning this feature on (by setting it to <literal>true</literal>) you will not need to add the library dependency on the consumer side.</simpara>
</listitem>
<listitem>
<simpara><emphasis role="strong">assertJsonSize</emphasis>: You can check the size of JSON arrays in the generated tests. This feature is disabled by default.</simpara>
</listitem>
</itemizedlist>
</section>
<section xml:id="gradle-single-base-class">
<title>Single Base Class for All Tests</title>
@@ -2827,6 +2961,7 @@ following sections:</simpara>
&lt;extensions&gt;true&lt;/extensions&gt;
&lt;configuration&gt;
&lt;packageWithBaseClasses&gt;com.example.fraud&lt;/packageWithBaseClasses&gt;
&lt;convertToYaml&gt;true&lt;/convertToYaml&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;</programlisting>
<simpara>You can read more in the
@@ -3089,6 +3224,15 @@ use the current Maven ones.</simpara>
</itemizedlist>
<simpara>We cache only non-snapshot, explicitly provided versions (for example
<literal>+</literal> or <literal>1.0.0.BUILD-SNAPSHOT</literal> won&#8217;t get cached). By default, this feature is turned on.</simpara>
<simpara>Below you can find a list of experimental features you can turn on via the plugin:</simpara>
<itemizedlist>
<listitem>
<simpara><emphasis role="strong">convertToYaml</emphasis>: converts all DSLs to the declarative, YAML format. This can be extremely useful when you&#8217;re using external libraries in your Groovy DSLs. By turning this feature on (by setting it to <literal>true</literal>) you will not need to add the library dependency on the consumer side.</simpara>
</listitem>
<listitem>
<simpara><emphasis role="strong">assertJsonSize</emphasis>: You can check the size of JSON arrays in the generated tests. This feature is disabled by default.</simpara>
</listitem>
</itemizedlist>
</section>
<section xml:id="maven-single-base">
<title>Single Base Class for All Tests</title>
@@ -6894,80 +7038,80 @@ protected static Pattern anyOf(String... values){
return Pattern.compile(values.collect({"^$it\$"}).join("|"))
}
Pattern onlyAlphaUnicode() {
return ONLY_ALPHA_UNICODE
RegexProperty onlyAlphaUnicode() {
return new RegexProperty(ONLY_ALPHA_UNICODE).asString()
}
Pattern alphaNumeric() {
return ALPHA_NUMERIC
RegexProperty alphaNumeric() {
return new RegexProperty(ALPHA_NUMERIC).asString()
}
Pattern number() {
return NUMBER
RegexProperty number() {
return new RegexProperty(NUMBER).asDouble()
}
Pattern positiveInt() {
return POSITIVE_INT
RegexProperty positiveInt() {
return new RegexProperty(POSITIVE_INT).asInteger()
}
Pattern anyBoolean() {
return TRUE_OR_FALSE
RegexProperty anyBoolean() {
return new RegexProperty(TRUE_OR_FALSE).asBooleanType()
}
Pattern anInteger() {
return INTEGER
RegexProperty anInteger() {
return new RegexProperty(INTEGER).asInteger()
}
Pattern aDouble() {
return DOUBLE
RegexProperty aDouble() {
return new RegexProperty(DOUBLE).asDouble()
}
Pattern ipAddress() {
return IP_ADDRESS
RegexProperty ipAddress() {
return new RegexProperty(IP_ADDRESS).asString()
}
Pattern hostname() {
return HOSTNAME_PATTERN
RegexProperty hostname() {
return new RegexProperty(HOSTNAME_PATTERN).asString()
}
Pattern email() {
return EMAIL
RegexProperty email() {
return new RegexProperty(EMAIL).asString()
}
Pattern url() {
return URL
RegexProperty url() {
return new RegexProperty(URL).asString()
}
Pattern httpsUrl() {
return HTTPS_URL
RegexProperty httpsUrl() {
return new RegexProperty(HTTPS_URL).asString()
}
Pattern uuid(){
return UUID
RegexProperty uuid(){
return new RegexProperty(UUID).asString()
}
Pattern isoDate() {
return ANY_DATE
RegexProperty isoDate() {
return new RegexProperty(ANY_DATE).asString()
}
Pattern isoDateTime() {
return ANY_DATE_TIME
RegexProperty isoDateTime() {
return new RegexProperty(ANY_DATE_TIME).asString()
}
Pattern isoTime() {
return ANY_TIME
RegexProperty isoTime() {
return new RegexProperty(ANY_TIME).asString()
}
Pattern iso8601WithOffset() {
return ISO8601_WITH_OFFSET
RegexProperty iso8601WithOffset() {
return new RegexProperty(ISO8601_WITH_OFFSET).asString()
}
Pattern nonEmpty() {
return NON_EMPTY
RegexProperty nonEmpty() {
return new RegexProperty(NON_EMPTY).asString()
}
Pattern nonBlank() {
return NON_BLANK
RegexProperty nonBlank() {
return new RegexProperty(NON_BLANK).asString()
}</programlisting>
<simpara>In your contract, you can use it as shown in the following example:</simpara>
<programlisting language="groovy" linenumbering="unnumbered">Contract dslWithOptionalsInString = Contract.make {
@@ -7539,7 +7683,7 @@ equal to the value provided in the contract.</simpara>
</listitem>
<listitem>
<simpara><literal>byRegex(&#8230;&#8203;)</literal>: The value taken from the consumer&#8217;s request via the provided JSON Path must
match the regex.</simpara>
match the regex. You can also pass the type of the expected matched value (e.g. <literal>asString()</literal>, <literal>asLong()</literal> etc.)</simpara>
</listitem>
<listitem>
<simpara><literal>byDate()</literal>: The value taken from the consumer&#8217;s request via the provided JSON Path must
@@ -7581,7 +7725,7 @@ the regex for an ISO Time value.</simpara>
<listitem>
<simpara><literal>byType()</literal>: The value taken from the producer&#8217;s response via the provided JSON Path needs to be
of the same type as the type defined in the body of the response in the contract.
<literal>byType</literal> can take a closure, in which you can set <literal>minOccurrence</literal> and <literal>maxOccurrence</literal>.
<literal>byType</literal> can take a closure, in which you can set <literal>minOccurrence</literal> and <literal>maxOccurrence</literal>. For the request side, you should use the closure to assert size of the collection.
That way, you can assert the size of the flattened collection. To check the size of an
unflattened collection, use a custom method with the <literal>byCommand(&#8230;&#8203;)</literal> testMatcher.</simpara>
</listitem>
@@ -7623,7 +7767,8 @@ what the types mean</emphasis></para>
<simpara>For YAML the structure of a matcher looks like this</simpara>
<programlisting language="yml" linenumbering="unnumbered">- path: $.foo
type: by_regex
value: bar</programlisting>
value: bar
regexType: as_string</programlisting>
<simpara>Or if you want to use one of the predefined regular expressions
<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]</literal>:</simpara>
@@ -7650,6 +7795,14 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
<listitem>
<simpara><literal>by_time</literal></simpara>
</listitem>
<listitem>
<simpara><literal>by_type</literal></simpara>
<itemizedlist>
<listitem>
<simpara>there are 2 additional fields accepted: <literal>minOccurrence</literal> and <literal>maxOccurrence</literal>.</simpara>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</listitem>
<listitem>
@@ -7687,6 +7840,30 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
</itemizedlist>
</listitem>
</itemizedlist>
<simpara>You can also define which type the regular expression corresponds to via the <literal>regexType</literal> field. Below you can find the allowed list of regular expression types:</simpara>
<itemizedlist>
<listitem>
<simpara>as_integer</simpara>
</listitem>
<listitem>
<simpara>as_double</simpara>
</listitem>
<listitem>
<simpara>as_float,</simpara>
</listitem>
<listitem>
<simpara>as_long</simpara>
</listitem>
<listitem>
<simpara>as_short</simpara>
</listitem>
<listitem>
<simpara>as_boolean</simpara>
</listitem>
<listitem>
<simpara>as_string</simpara>
</listitem>
</itemizedlist>
<simpara>Consider the following example:</simpara>
<formalpara>
<title>Groovy DSL</title>
@@ -7710,12 +7887,12 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
]
])
bodyMatchers {
jsonPath('$.duck', byRegex("[0-9]{3}"))
jsonPath('$.duck', byRegex("[0-9]{3}").asInteger())
jsonPath('$.duck', byEquality())
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()).asString())
jsonPath('$.alpha', byEquality())
jsonPath('$.number', byRegex(number()))
jsonPath('$.aBoolean', byRegex(anyBoolean()))
jsonPath('$.number', byRegex(number()).asInteger())
jsonPath('$.aBoolean', byRegex(anyBoolean()).asBooleanType())
jsonPath('$.date', byDate())
jsonPath('$.dateTime', byTimestamp())
jsonPath('$.time', byTime())
@@ -7759,18 +7936,18 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
])
bodyMatchers {
// asserts the jsonpath value against manual regex
jsonPath('$.duck', byRegex("[0-9]{3}"))
jsonPath('$.duck', byRegex("[0-9]{3}").asInteger())
// asserts the jsonpath value against the provided value
jsonPath('$.duck', byEquality())
// asserts the jsonpath value against some default regex
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()).asString())
jsonPath('$.alpha', byEquality())
jsonPath('$.number', byRegex(number()))
jsonPath('$.positiveInteger', byRegex(anInteger()))
jsonPath('$.negativeInteger', byRegex(anInteger()))
jsonPath('$.positiveDecimalNumber', byRegex(aDouble()))
jsonPath('$.negativeDecimalNumber', byRegex(aDouble()))
jsonPath('$.aBoolean', byRegex(anyBoolean()))
jsonPath('$.number', byRegex(number()).asInteger())
jsonPath('$.positiveInteger', byRegex(anInteger()).asInteger())
jsonPath('$.negativeInteger', byRegex(anInteger()).asInteger())
jsonPath('$.positiveDecimalNumber', byRegex(aDouble()).asDouble())
jsonPath('$.negativeDecimalNumber', byRegex(aDouble()).asDouble())
jsonPath('$.aBoolean', byRegex(anyBoolean()).asBooleanType())
// asserts vs inbuilt time related regex
jsonPath('$.date', byDate())
jsonPath('$.dateTime', byTimestamp())
@@ -7844,6 +8021,20 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
key:
"complex.key": 'foo'
nullValue: null
valueWithMin:
- 1
- 2
- 3
valueWithMax:
- 1
- 2
- 3
valueWithMinMax:
- 1
- 2
- 3
valueWithMinEmpty: []
valueWithMaxEmpty: []
matchers:
url:
regex: /get/[0-9]
@@ -7906,6 +8097,16 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
type: by_equality
- path: $.nullvalue
type: by_null
- path: $.valueWithMin
type: by_type
minOccurrence: 1
- path: $.valueWithMax
type: by_type
maxOccurrence: 3
- path: $.valueWithMinMax
type: by_type
minOccurrence: 1
maxOccurrence: 3
response:
status: 200
cookies:
@@ -8077,51 +8278,60 @@ the method name and passed the proper JSON path as a parameter to it.</simpara>
<programlisting language="json" linenumbering="unnumbered"> '''
{
"request" : {
"urlPath" : "/get",
"method" : "POST",
"headers" : {
"Content-Type" : {
"matches" : "application/json.*"
}
},
"bodyPatterns" : [ {
"matchesJsonPath" : "$[?(@.['valueWithoutAMatcher'] == 'foo')]"
}, {
"matchesJsonPath" : "$[?(@.['valueWithTypeMatch'] == 'string')]"
}, {
"matchesJsonPath" : "$.['list'].['some'].['nested'][?(@.['anothervalue'] == 4)]"
}, {
"matchesJsonPath" : "$.['list'].['someother'].['nested'][?(@.['anothervalue'] == 4)]"
}, {
"matchesJsonPath" : "$.['list'].['someother'].['nested'][?(@.['json'] == 'with value')]"
}, {
"matchesJsonPath" : "$[?(@.duck =~ /([0-9]{3})/)]"
}, {
"matchesJsonPath" : "$[?(@.duck == 123)]"
}, {
"matchesJsonPath" : "$[?(@.alpha =~ /([\\\\p{L}]*)/)]"
}, {
"matchesJsonPath" : "$[?(@.alpha == 'abc')]"
}, {
"matchesJsonPath" : "$[?(@.number =~ /(-?(\\\\d*\\\\.\\\\d+|\\\\d+))/)]"
}, {
"matchesJsonPath" : "$[?(@.aBoolean =~ /((true|false))/)]"
}, {
"matchesJsonPath" : "$[?(@.date =~ /((\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))/)]"
}, {
"matchesJsonPath" : "$[?(@.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]))/)]"
}, {
"matchesJsonPath" : "$[?(@.time =~ /((2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]))/)]"
}, {
"matchesJsonPath" : "$.list.some.nested[?(@.json =~ /(.*)/)]"
} ]
"urlPath" : "/get",
"method" : "POST",
"headers" : {
"Content-Type" : {
"matches" : "application/json.*"
}
},
"bodyPatterns" : [ {
"matchesJsonPath" : "$.['list'].['some'].['nested'][?(@.['anothervalue'] == 4)]"
}, {
"matchesJsonPath" : "$[?(@.['valueWithoutAMatcher'] == 'foo')]"
}, {
"matchesJsonPath" : "$[?(@.['valueWithTypeMatch'] == 'string')]"
}, {
"matchesJsonPath" : "$.['list'].['someother'].['nested'][?(@.['json'] == 'with value')]"
}, {
"matchesJsonPath" : "$.['list'].['someother'].['nested'][?(@.['anothervalue'] == 4)]"
}, {
"matchesJsonPath" : "$[?(@.duck =~ /([0-9]{3})/)]"
}, {
"matchesJsonPath" : "$[?(@.duck == 123)]"
}, {
"matchesJsonPath" : "$[?(@.alpha =~ /([\\\\p{L}]*)/)]"
}, {
"matchesJsonPath" : "$[?(@.alpha == 'abc')]"
}, {
"matchesJsonPath" : "$[?(@.number =~ /(-?(\\\\d*\\\\.\\\\d+|\\\\d+))/)]"
}, {
"matchesJsonPath" : "$[?(@.aBoolean =~ /((true|false))/)]"
}, {
"matchesJsonPath" : "$[?(@.date =~ /((\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))/)]"
}, {
"matchesJsonPath" : "$[?(@.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]))/)]"
}, {
"matchesJsonPath" : "$[?(@.time =~ /((2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]))/)]"
}, {
"matchesJsonPath" : "$.list.some.nested[?(@.json =~ /(.*)/)]"
}, {
"matchesJsonPath" : "$[?(@.valueWithMin.size() &gt;= 1)]"
}, {
"matchesJsonPath" : "$[?(@.valueWithMax.size() &lt;= 3)]"
}, {
"matchesJsonPath" : "$[?(@.valueWithMinMax.size() &gt;= 1 &amp;&amp; @.valueWithMinMax.size() &lt;= 3)]"
}, {
"matchesJsonPath" : "$[?(@.valueWithOccurrence.size() &gt;= 4 &amp;&amp; @.valueWithOccurrence.size() &lt;= 4)]"
} ]
},
"response" : {
"status" : 200,
"body" : "{\\"date\\":\\"2017-01-01\\",\\"dateTime\\":\\"2017-01-01T01:23:45\\",\\"number\\":123,\\"aBoolean\\":true,\\"duck\\":123,\\"alpha\\":\\"abc\\",\\"valueWithMin\\":[1,2,3],\\"time\\":\\"01:02:34\\",\\"valueWithTypeMatch\\":\\"string\\",\\"valueWithMax\\":[1,2,3],\\"valueWithMinMax\\":[1,2,3],\\"valueWithoutAMatcher\\":\\"foo\\"}",
"headers" : {
"Content-Type" : "application/json"
}
"status" : 200,
"body" : "{\\"date\\":\\"2017-01-01\\",\\"dateTime\\":\\"2017-01-01T01:23:45\\",\\"aBoolean\\":true,\\"valueWithMax\\":[1,2,3],\\"valueWithOccurrence\\":[1,2,3,4],\\"number\\":123,\\"duck\\":123,\\"alpha\\":\\"abc\\",\\"valueWithMin\\":[1,2,3],\\"time\\":\\"01:02:34\\",\\"valueWithTypeMatch\\":\\"string\\",\\"valueWithMinMax\\":[1,2,3],\\"valueWithoutAMatcher\\":\\"foo\\"}",
"headers" : {
"Content-Type" : "application/json"
},
"transformers" : [ "response-template" ]
}
}
'''</programlisting>
@@ -8610,11 +8820,16 @@ request:
url: /users/1
response:
status: 200
---
request:
method: POST
url: /users/2
response:
status: 200
---
request:
method: POST
url: /users/3
response:
status: 200</programlisting>
</para>
@@ -8974,7 +9189,7 @@ visible in your Groovy files. The following examples show how to test the depend
<formalpara role="secondary">
<title>Gradle</title>
<para>
<programlisting language="groovy" linenumbering="unnumbered">testCompile("com.example:beer-common:0.0.1-SNAPSHOT")</programlisting>
<programlisting language="groovy" linenumbering="unnumbered">testCompile("com.example:beer-common:0.0.1.BUILD-SNAPSHOT")</programlisting>
</para>
</formalpara>
</section>
@@ -9013,7 +9228,7 @@ following example:</simpara>
<formalpara role="secondary">
<title>Gradle</title>
<para>
<programlisting language="groovy" linenumbering="unnumbered">classpath "com.example:beer-common:0.0.1-SNAPSHOT"</programlisting>
<programlisting language="groovy" linenumbering="unnumbered">classpath "com.example:beer-common:0.0.1.BUILD-SNAPSHOT"</programlisting>
</para>
</formalpara>
</section>
@@ -9062,6 +9277,9 @@ then:
}
}
}</programlisting>
<important>
<simpara>You can set the Spring Cloud Contract plugin up by setting <literal>convertToYaml</literal> to <literal>true</literal>. That way you will NOT have to add the dependency with the extended functionality to the consumer side, since the consumer side will be using YAML contracts instead of Groovy ones.</simpara>
</important>
</section>
</section>
</chapter>