Sync docs from master to gh-pages
This commit is contained in:
@@ -14,14 +14,14 @@ produced by Spring Cloud Contract Verifier.</li><li class="listitem">Messaging r
|
||||
Integration, Spring Cloud Stream, Spring AMQP, and Apache Camel. You can also set your
|
||||
own integrations.</li><li class="listitem">Acceptance tests (in JUnit or Spock) are used to verify if server-side implementation
|
||||
of the API is compliant with the contract (<span class="emphasis"><em>server tests</em></span>). A full test is generated by
|
||||
Spring Cloud Contract Verifier.</li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_a_contract_verifier" href="#_why_a_contract_verifier"></a>2.1 Why a Contract Verifier?</h2></div></div></div><p>Assume that we have a system consisting of multiple microservices:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/Deps.png" alt="Microservices Architecture"></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_testing_issues" href="#_testing_issues"></a>2.1.1 Testing issues</h3></div></div></div><p>If we wanted to test the application in top left corner to determine whether it can
|
||||
Spring Cloud Contract Verifier.</li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_a_contract_verifier" href="#_why_a_contract_verifier"></a>2.1 Why a Contract Verifier?</h2></div></div></div><p>Assume that we have a system consisting of multiple microservices:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.2.x/docs/src/main/asciidoc/images/Deps.png" alt="Microservices Architecture"></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_testing_issues" href="#_testing_issues"></a>2.1.1 Testing issues</h3></div></div></div><p>If we wanted to test the application in top left corner to determine whether it can
|
||||
communicate with other services, we could do one of two things:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Deploy all microservices and perform end-to-end tests.</li><li class="listitem">Mock other microservices in unit/integration tests.</li></ul></div><p>Both have their advantages but also a lot of disadvantages.</p><p><span class="strong"><strong>Deploy all microservices and perform end to end tests</strong></span></p><p>Advantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Simulates production.</li><li class="listitem">Tests real communication between services.</li></ul></div><p>Disadvantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">To test one microservice, we have to deploy 6 microservices, a couple of databases,
|
||||
etc.</li><li class="listitem">The environment where the tests run is locked for a single suite of tests (nobody else
|
||||
would be able to run the tests in the meantime).</li><li class="listitem">They take a long time to run.</li><li class="listitem">The feedback comes very late in the process.</li><li class="listitem">They are extremely hard to debug.</li></ul></div><p><span class="strong"><strong>Mock other microservices in unit/integration tests</strong></span></p><p>Advantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">They provide very fast feedback.</li><li class="listitem">They have no infrastructure requirements.</li></ul></div><p>Disadvantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The implementor of the service creates stubs that might have nothing to do with
|
||||
reality.</li><li class="listitem">You can go to production with passing tests and failing production.</li></ul></div><p>To solve the aforementioned issues, Spring Cloud Contract Verifier with Stub Runner was
|
||||
created. The main idea is to give you very fast feedback, without the need to set up the
|
||||
whole world of microservices. If you work on stubs, then the only applications you need
|
||||
are those that your application directly uses.</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/Stubs2.png" alt="Stubbed Services"></div></div><p>Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were
|
||||
are those that your application directly uses.</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.2.x/docs/src/main/asciidoc/images/Stubs2.png" alt="Stubbed Services"></div></div><p>Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were
|
||||
created by the service that you’re calling. Also, if you can use them, it means that they
|
||||
were tested against the producer’s side. In short, you can trust those stubs.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_purposes" href="#_purposes"></a>2.2 Purposes</h2></div></div></div><p>The main purposes of Spring Cloud Contract Verifier with Stub Runner are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">To ensure that WireMock/Messaging stubs (used when developing the client) do exactly
|
||||
what the actual server-side implementation does.</li><li class="listitem">To promote ATDD method and Microservices architectural style.</li><li class="listitem">To provide a way to publish changes in contracts that are immediately visible on both
|
||||
@@ -96,7 +96,7 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
}
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body([
|
||||
fraudCheckStatus: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejection.reason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
|
||||
@@ -264,7 +264,7 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
}
|
||||
}
|
||||
response { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (6)</span>
|
||||
status <span class="hl-number">200</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (7)</span>
|
||||
status OK() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (7)</span>
|
||||
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (8)</span>
|
||||
fraudCheckStatus: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejection.reason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
|
||||
@@ -398,8 +398,8 @@ us. The current implementation of our system grants loans to everybody.</p><p>As
|
||||
sprint, we must develop a new feature: if a client wants to borrow too much money, then
|
||||
we mark the client as a fraud.</p><p>Technical remark - Fraud Detection has an <code class="literal">artifact-id</code> of <code class="literal">http-server</code>, while Loan
|
||||
Issuance has an artifact-id of <code class="literal">http-client</code>, and both have a <code class="literal">group-id</code> of <code class="literal">com.example</code>.</p><p>Social remark - both client and server development teams need to communicate directly and
|
||||
discuss changes while going through the process. CDC is all about communication.</p><p>The <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/dsl/http-server" target="_top">server
|
||||
side code is available here</a> and <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/standalone/dsl/http-client" target="_top">the
|
||||
discuss changes while going through the process. CDC is all about communication.</p><p>The <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.2.x/samples/standalone/dsl/http-server" target="_top">server
|
||||
side code is available here</a> and <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.2.x/samples/standalone/dsl/http-client" target="_top">the
|
||||
client code here</a>.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>In this case, the producer owns the contracts. Physically, all the contract are
|
||||
in the producer’s repository.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_technical_note" href="#_technical_note"></a>2.4.1 Technical note</h3></div></div></div><p>If using the <span class="strong"><strong>SNAPSHOT</strong></span> / <span class="strong"><strong>Milestone</strong></span> / <span class="strong"><strong>Release Candidate</strong></span> versions please add the
|
||||
following section to your build:</p><p class="primary"><b>Maven. </b>
|
||||
@@ -501,7 +501,7 @@ org.springframework.cloud.contract.spec.Contract.make {
|
||||
}
|
||||
}
|
||||
response { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (6)</span>
|
||||
status <span class="hl-number">200</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (7)</span>
|
||||
status OK() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (7)</span>
|
||||
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (8)</span>
|
||||
fraudCheckStatus: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejection.reason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
|
||||
@@ -841,7 +841,7 @@ for time and UUID are simplified and most likely invalid but we want to keep thi
|
||||
])
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body([
|
||||
time : value(producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]'</span>)),
|
||||
id: value([producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'</span>))
|
||||
@@ -896,15 +896,15 @@ one to one to the contents of the repo.</p><p>Example of a <code class="literal"
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><parent></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>2.0.0.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>1.5.10.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><relativePath /></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></parent></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><properties></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project.build.sourceEncoding></span>UTF-8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></project.build.sourceEncoding></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><java.version></span>1.8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></java.version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><spring-cloud-contract.version></span>2.0.0.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></spring-cloud-contract.version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><spring-cloud-dependencies.version></span>Finchley.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></spring-cloud-dependencies.version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><spring-cloud-contract.version></span>1.2.4.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></spring-cloud-contract.version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><spring-cloud-dependencies.version></span>Edgware.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></spring-cloud-dependencies.version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><excludeBuildFolders></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></excludeBuildFolders></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></properties></span>
|
||||
|
||||
@@ -1061,7 +1061,6 @@ of the JAR containing the contracts:</p><pre class="programlisting"><span xmlns:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsMode></span>REMOTE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsMode></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsRepositoryUrl></span>http://link/to/your/nexus/or/artifactory/or/sth<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsRepositoryUrl></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractDependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example.standalone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
@@ -1642,7 +1641,7 @@ goal.</p><p>For Groovy Spock code, use the following:</p><pre class="programlist
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></testSources></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>To ensure that provider side is compliant with defined contracts, you need to invoke
|
||||
<code class="literal">mvn generateTest test</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-sts" href="#maven-sts"></a>4.2.11 Maven Plugin and STS</h3></div></div></div><p>If you see the following exception while using STS:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/docs/src/main/asciidoc/images/sts_exception.png" alt="STS Exception"></div></div><p>When you click on the error marker you should see something like this:</p><pre class="programlisting"> plugin:<span class="hl-number">1.1</span>.<span class="hl-number">0.</span>M1:convert:default-convert:process-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
|
||||
<code class="literal">mvn generateTest test</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-sts" href="#maven-sts"></a>4.2.11 Maven Plugin and STS</h3></div></div></div><p>If you see the following exception while using STS:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.2.x/docs/src/main/asciidoc/images/sts_exception.png" alt="STS Exception"></div></div><p>When you click on the error marker you should see something like this:</p><pre class="programlisting"> plugin:<span class="hl-number">1.1</span>.<span class="hl-number">0.</span>M1:convert:default-convert:process-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
|
||||
cloud-contract-maven-plugin:<span class="hl-number">1.1</span>.<span class="hl-number">0.</span>M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:<span class="hl-number">145</span>) at
|
||||
org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:<span class="hl-number">331</span>) at org.eclipse.m2e.core.internal.embedder.MavenImpl$<span class="hl-number">11.</span>call(MavenImpl.java:<span class="hl-number">1362</span>) at
|
||||
...
|
||||
@@ -2248,8 +2247,8 @@ producer stubs.</p></td></tr></table></div><p>The producer would setup the contr
|
||||
└── com.example
|
||||
└── beer-api-producer-restdocs
|
||||
└── nested
|
||||
└── contract3.groovy</pre><p>To achieve proper stub packaging.</p><p>Or using the <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/pom.xml" target="_top">Maven <code class="literal">assembly</code> plugin</a> or
|
||||
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/build.gradle" target="_top">Gradle Jar</a> task you have to create the following
|
||||
└── contract3.groovy</pre><p>To achieve proper stub packaging.</p><p>Or using the <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/2.0.x/producer_with_restdocs/pom.xml" target="_top">Maven <code class="literal">assembly</code> plugin</a> or
|
||||
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/2.0.x/producer_with_restdocs/build.gradle" target="_top">Gradle Jar</a> task you have to create the following
|
||||
structure in your stubs jar.</p><pre class="programlisting">└── META-INF
|
||||
└── com.example
|
||||
└── beer-api-producer-restdocs
|
||||
@@ -2508,7 +2507,7 @@ Below you can find an example of achieving the same result by setting values on
|
||||
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
||||
repositoryRoot = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:m2repo/repository/"</span>)</pre><p>Stub Runner Spring registers environment variables in the following manner
|
||||
for every registered WireMock server. Example for Stub Runner ids
|
||||
<code class="literal">com.example:foo</code>, <code class="literal">com.example:bar</code>.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">stubrunner.runningstubs.foo.port</code></li><li class="listitem"><code class="literal">stubrunner.runningstubs.bar.port</code></li></ul></div><p>Which you can reference in your code.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_spring_cloud" href="#_stub_runner_spring_cloud"></a>6.5 Stub Runner Spring Cloud</h2></div></div></div><p>Stub Runner can integrate with Spring Cloud.</p><p>For real life examples you can check the</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer" target="_top">producer app sample</a></li><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_with_discovery" target="_top">consumer app sample</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stubbing_service_discovery" href="#_stubbing_service_discovery"></a>6.5.1 Stubbing Service Discovery</h3></div></div></div><p>The most important feature of <code class="literal">Stub Runner Spring Cloud</code> is the fact that it’s stubbing</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">DiscoveryClient</code></li><li class="listitem"><code class="literal">Ribbon</code> <code class="literal">ServerList</code></li></ul></div><p>that means that regardless of the fact whether you’re using Zookeeper, Consul, Eureka or anything else, you don’t need that in your tests.
|
||||
<code class="literal">com.example:foo</code>, <code class="literal">com.example:bar</code>.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">stubrunner.runningstubs.foo.port</code></li><li class="listitem"><code class="literal">stubrunner.runningstubs.bar.port</code></li></ul></div><p>Which you can reference in your code.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_spring_cloud" href="#_stub_runner_spring_cloud"></a>6.5 Stub Runner Spring Cloud</h2></div></div></div><p>Stub Runner can integrate with Spring Cloud.</p><p>For real life examples you can check the</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/producer" target="_top">producer app sample</a></li><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.0.x/consumer_with_discovery" target="_top">consumer app sample</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stubbing_service_discovery" href="#_stubbing_service_discovery"></a>6.5.1 Stubbing Service Discovery</h3></div></div></div><p>The most important feature of <code class="literal">Stub Runner Spring Cloud</code> is the fact that it’s stubbing</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">DiscoveryClient</code></li><li class="listitem"><code class="literal">Ribbon</code> <code class="literal">ServerList</code></li></ul></div><p>that means that regardless of the fact whether you’re using Zookeeper, Consul, Eureka or anything else, you don’t need that in your tests.
|
||||
We’re starting WireMock instances of your dependencies and we’re telling your application whenever you’re using <code class="literal">Feign</code>, load balanced <code class="literal">RestTemplate</code>
|
||||
or <code class="literal">DiscoveryClient</code> directly, to call those stubbed servers instead of calling the real Service Discovery tool.</p><p>For example this test will pass</p><pre class="programlisting">def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should make service discovery work'</span>() {
|
||||
expect: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'WireMocks are running'</span>
|
||||
@@ -2672,7 +2671,7 @@ There are 2 consumers: <code class="literal">foo-consumer</code> and <code class
|
||||
method GET()
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body(
|
||||
foo: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>
|
||||
}
|
||||
@@ -2681,7 +2680,7 @@ response {
|
||||
method GET()
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body(
|
||||
bar: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>
|
||||
}
|
||||
@@ -3092,7 +3091,7 @@ the <code class="literal">Contract</code> class: <code class="literal">import or
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span> }
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}</pre><p>The following is a complete example of a YAML contract definition:</p><pre class="programlisting">description: Some description
|
||||
name: some name
|
||||
@@ -3242,7 +3241,7 @@ Contract.make {
|
||||
url(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/1"</span>)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body(file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response.json"</span>))
|
||||
headers {
|
||||
contentType(textPlain())
|
||||
@@ -3475,7 +3474,7 @@ body:
|
||||
)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -3563,7 +3562,7 @@ following code shows an example:</p><p><b>Groovy DSL. </b>
|
||||
response {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Status code sent by the server</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// in response to request specified above.</span>
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p><b>YAML. </b>
|
||||
@@ -3571,7 +3570,9 @@ following code shows an example:</p><p><b>Groovy DSL. </b>
|
||||
...
|
||||
status: 200</pre><p>
|
||||
</p><p>Besides status, the response may contain <span class="strong"><strong>headers</strong></span> and a <span class="strong"><strong>body</strong></span>, both of which are
|
||||
specified the same way as in the request (see the previous paragraph).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_dynamic_properties" href="#_dynamic_properties"></a>8.5 Dynamic properties</h2></div></div></div><p>The contract can contain some dynamic properties: timestamps, IDs, and so on. You do not
|
||||
specified the same way as in the request (see the previous paragraph).</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Via the Groovy DSL you can reference the <code class="literal">org.springframework.cloud.contract.spec.internal.HttpStatus</code>
|
||||
methods to provide a meaningful status instead of a digit. E.g. you can call
|
||||
<code class="literal">OK()</code> for a status <code class="literal">200</code> or <code class="literal">BAD_REQUEST()</code> for <code class="literal">400</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_dynamic_properties" href="#_dynamic_properties"></a>8.5 Dynamic properties</h2></div></div></div><p>The contract can contain some dynamic properties: timestamps, IDs, and so on. You do not
|
||||
want to force the consumers to stub their clocks to always return the same value of time
|
||||
so that it gets matched by the stub.</p><p>For Groovy DSL you can provide the dynamic parts in your contracts
|
||||
in two ways: pass them directly in the body or set them in separate sections called
|
||||
@@ -3595,7 +3596,7 @@ need to use patterns and not exact values both for your test and your server sid
|
||||
url $(consumer(~/\/[<span class="hl-number">0</span>-<span class="hl-number">9</span>]{<span class="hl-number">2</span>}/), producer(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/12'</span>))
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body(
|
||||
id: $(anyNumber()),
|
||||
surname: $(
|
||||
@@ -3626,7 +3627,7 @@ the provided regular expression. The following code shows an example:</p><pre cl
|
||||
}
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body([
|
||||
responseElement: $(producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{7}'</span>)))
|
||||
])
|
||||
@@ -3639,6 +3640,7 @@ generated for request and response.</p><p>Spring Cloud Contract comes with a ser
|
||||
use in your contracts, as shown in the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern TRUE_OR_FALSE = Pattern.compile(/(true|false)/)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern ONLY_ALPHA_UNICODE = Pattern.compile(/[\p{L}]*/)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern NUMBER = Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'-?(\\d*\\.\\d+|\\d+)'</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern DOUBLE = Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'-?(\\d*\\.\\d+)'</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern IP_ADDRESS = Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])'</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern HOSTNAME_PATTERN = Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?'</span>)
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Pattern EMAIL = Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}'</span>)
|
||||
@@ -3667,6 +3669,10 @@ Pattern anyBoolean() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> TRUE_OR_FALSE
|
||||
}
|
||||
|
||||
Pattern aDouble() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> DOUBLE
|
||||
}
|
||||
|
||||
Pattern ipAddress() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> IP_ADDRESS
|
||||
}
|
||||
@@ -3819,7 +3825,7 @@ following code shows an example of the contract portion of the test case:</p><pr
|
||||
path: $(consumer(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/api/12'</span>), producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'^/api/[0-9]{2}$'</span>))),
|
||||
correlationId: $(consumer(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'1223456'</span>), producer(execute(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'isProperCorrelationId($it)'</span>)))
|
||||
)
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}</pre><p>The following code shows the base class portion of the test case:</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 {
|
||||
|
||||
@@ -3850,7 +3856,7 @@ is applied for the whole body - not for parts of it.</p></td></tr></table></div>
|
||||
)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}</pre><p>The preceding example results in calling the <code class="literal">hashCode()</code> method in the request body.
|
||||
It should resemble the following code:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
|
||||
@@ -3889,7 +3895,7 @@ matches the JSON Path. E.g. for json path <code class="literal">$.foo</code> - <
|
||||
body(foo: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>, baz: <span class="hl-number">5</span>)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
headers {
|
||||
header(authorization(), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo ${fromRequest().header(authorization())} bar"</span>)
|
||||
}
|
||||
@@ -4108,7 +4114,7 @@ email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_e
|
||||
}
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body([
|
||||
duck: <span class="hl-number">123</span>,
|
||||
alpha: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"abc"</span>,
|
||||
@@ -4417,7 +4423,7 @@ collection.</p></td></tr></table></div><p>Consider the following example:</p><pr
|
||||
url(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/foo"</span>)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body(events: [[
|
||||
operation : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'EXPORT'</span>,
|
||||
eventId : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'16f1ed75-0bcc-4f0d-a04d-3121798faf99'</span>,
|
||||
@@ -4481,7 +4487,7 @@ provide a <code class="literal">sync()</code> method in the <code class="literal
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/get'</span>
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Passed'</span>
|
||||
async()
|
||||
}
|
||||
@@ -4514,7 +4520,7 @@ socket.</p><p>Consider the following contract:</p><pre class="programlisting">or
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/my-context-path/url'</span>
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}</pre><p>The following example shows how to set up a base class and Rest Assured:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> io.restassured.RestAssured;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.junit.Before;
|
||||
@@ -4671,7 +4677,7 @@ following example:</p><p><b>Groovy DSL. </b>
|
||||
url(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/users/1'</span>)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
},
|
||||
Contract.make {
|
||||
@@ -4680,7 +4686,7 @@ following example:</p><p><b>Groovy DSL. </b>
|
||||
url(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/users/2'</span>)
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
}
|
||||
}
|
||||
]</pre><p>
|
||||
@@ -5630,7 +5636,7 @@ Contract.make {
|
||||
}
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
status OK()
|
||||
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
|
||||
</span> bar
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">')
|
||||
|
||||
Reference in New Issue
Block a user