Redirects to contract project website
This commit is contained in:
committed by
GitHub
parent
dd9d263f83
commit
7126694f51
@@ -1,700 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Asciidoctor 1.5.7.1">
|
||||
<title>Spring Cloud Contract WireMock</title>
|
||||
<link rel="stylesheet" href="css/spring.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<meta http-equiv="refresh" content="1; url=https://spring.io/projects/spring-cloud-contract#learn">
|
||||
|
||||
<style>
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.switch {
|
||||
border-width: 1px 1px 0 1px;
|
||||
border-style: solid;
|
||||
border-color: #7a2518;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.switch--item {
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
color: #7a2518;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.switch--item:not(:first-child) {
|
||||
border-width: 0 0 0 1px;
|
||||
border-style: solid;
|
||||
border-color: #7a2518;
|
||||
}
|
||||
|
||||
.switch--item.selected {
|
||||
background-color: #7a2519;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
function addBlockSwitches() {
|
||||
$('.primary').each(function() {
|
||||
primary = $(this);
|
||||
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
|
||||
primary.children('.title').remove();
|
||||
});
|
||||
$('.secondary').each(function(idx, node) {
|
||||
secondary = $(node);
|
||||
primary = findPrimary(secondary);
|
||||
switchItem = createSwitchItem(secondary, primary.children('.switch'));
|
||||
switchItem.content.addClass('hidden');
|
||||
findPrimary(secondary).append(switchItem.content);
|
||||
secondary.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function createBlockSwitch(primary) {
|
||||
blockSwitch = $('<div class="switch"></div>');
|
||||
primary.prepend(blockSwitch);
|
||||
return blockSwitch;
|
||||
}
|
||||
|
||||
function findPrimary(secondary) {
|
||||
candidate = secondary.prev();
|
||||
while (!candidate.is('.primary')) {
|
||||
candidate = candidate.prev();
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
function createSwitchItem(block, blockSwitch) {
|
||||
blockName = block.children('.title').text();
|
||||
content = block.children('.content').first().append(block.next('.colist'));
|
||||
item = $('<div class="switch--item">' + blockName + '</div>');
|
||||
item.on('click', '', content, function(e) {
|
||||
$(this).addClass('selected');
|
||||
$(this).siblings().removeClass('selected');
|
||||
e.data.siblings('.content').addClass('hidden');
|
||||
e.data.removeClass('hidden');
|
||||
});
|
||||
blockSwitch.append(item);
|
||||
return {'item': item, 'content': content};
|
||||
}
|
||||
|
||||
$(addBlockSwitches);
|
||||
<script>
|
||||
window.location.href = "https://spring.io/projects/spring-cloud-contract#learn"
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body class="book toc2 toc-left">
|
||||
<div id="header">
|
||||
<div id="toc" class="toc2">
|
||||
<div id="toctitle">Table of Contents</div>
|
||||
<ul class="sectlevel1">
|
||||
<li><a href="#_spring_cloud_contract_wiremock">Spring Cloud Contract WireMock</a>
|
||||
<ul class="sectlevel2">
|
||||
<li><a href="#_registering_stubs_automatically">Registering Stubs Automatically</a></li>
|
||||
<li><a href="#_using_files_to_specify_the_stub_bodies">Using Files to Specify the Stub Bodies</a></li>
|
||||
<li><a href="#_alternative_using_junit_rules">Alternative: Using JUnit Rules</a></li>
|
||||
<li><a href="#_relaxed_ssl_validation_for_rest_template">Relaxed SSL Validation for Rest Template</a></li>
|
||||
<li><a href="#_wiremock_and_spring_mvc_mocks">WireMock and Spring MVC Mocks</a></li>
|
||||
<li><a href="#_customization_of_wiremock_configuration">Customization of WireMock configuration</a></li>
|
||||
<li><a href="#_generating_stubs_using_rest_docs">Generating Stubs using REST Docs</a></li>
|
||||
<li><a href="#_generating_contracts_by_using_rest_docs">Generating Contracts by Using REST Docs</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div class="sect1">
|
||||
<h2 id="_spring_cloud_contract_wiremock"><a class="link" href="#_spring_cloud_contract_wiremock">Spring Cloud Contract WireMock</a></h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The Spring Cloud Contract WireMock modules let you use <a href="https://github.com/tomakehurst/wiremock">WireMock</a> in a
|
||||
Spring Boot application. Check out the
|
||||
<a href="https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples">samples</a>
|
||||
for more details.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you have a Spring Boot application that uses Tomcat as an embedded server (which is
|
||||
the default with <code>spring-boot-starter-web</code>), you can add
|
||||
<code>spring-cloud-starter-contract-stub-runner</code> to your classpath and add <code>@AutoConfigureWireMock</code> in
|
||||
order to be able to use Wiremock in your tests. Wiremock runs as a stub server and you
|
||||
can register stub behavior using a Java API or via static JSON declarations as part of
|
||||
your test. The following code shows an example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureWireMock(port = 0)
|
||||
public class WiremockForDocsTests {
|
||||
<title>Page Redirection</title>
|
||||
|
||||
// A service that calls out over HTTP
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.service.setBase("http://localhost:"
|
||||
+ this.environment.getProperty("wiremock.server.port"));
|
||||
}
|
||||
|
||||
// Using the WireMock APIs in the normal way:
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Stubbing WireMock
|
||||
stubFor(get(urlEqualTo("/resource")).willReturn(aResponse()
|
||||
.withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To start the stub server on a different port use (for example),
|
||||
<code>@AutoConfigureWireMock(port=9999)</code>. For a random port, use a value of <code>0</code>. The stub
|
||||
server port can be bound in the test application context with the "wiremock.server.port"
|
||||
property. Using <code>@AutoConfigureWireMock</code> adds a bean of type <code>WiremockConfiguration</code> to
|
||||
your test application context, where it will be cached in between methods and classes
|
||||
having the same context, the same as for Spring integration tests. Also you can inject a bean of type <code>WireMockServer</code> into your test.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_registering_stubs_automatically"><a class="link" href="#_registering_stubs_automatically">Registering Stubs Automatically</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>If you use <code>@AutoConfigureWireMock</code>, it registers WireMock JSON stubs from the file
|
||||
system or classpath (by default, from <code>file:src/test/resources/mappings</code>). You can
|
||||
customize the locations using the <code>stubs</code> attribute in the annotation, which can be an
|
||||
Ant-style resource pattern or a directory. In the case of a directory, <code><strong>*/</strong>.json</code> is
|
||||
appended. The following code shows an example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre>@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureWireMock(stubs="classpath:/stubs")
|
||||
public class WiremockImportApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admonitionblock note">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-note" title="Note"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
Actually, WireMock always loads mappings from <code>src/test/resources/mappings</code> <strong>as
|
||||
well as</strong> the custom locations in the stubs attribute. To change this behavior, you can
|
||||
also specify a files root as described in the next section of this document.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you’re using Spring Cloud Contract’s default stub jars, then your
|
||||
stubs are stored under <code>/META-INF/group-id/artifact-id/versions/mappings/</code> folder. If you want to register all stubs from that location, from all embedded JARs, then it’s enough to use the following syntax.</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@AutoConfigureWireMock(port = 0, stubs = "classpath*:/META-INF/**/mappings/**/*.json")</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_using_files_to_specify_the_stub_bodies"><a class="link" href="#_using_files_to_specify_the_stub_bodies">Using Files to Specify the Stub Bodies</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>WireMock can read response bodies from files on the classpath or the file system. In that
|
||||
case, you can see in the JSON DSL that the response has a <code>bodyFileName</code> instead of a
|
||||
(literal) <code>body</code>. The files are resolved relative to a root directory (by default,
|
||||
<code>src/test/resources/__files</code>). To customize this location you can set the <code>files</code>
|
||||
attribute in the <code>@AutoConfigureWireMock</code> annotation to the location of the parent
|
||||
directory (in other words, <code>__files</code> is a subdirectory). You can use Spring resource
|
||||
notation to refer to <code>file:…​</code> or <code>classpath:…​</code> locations. Generic URLs are not
|
||||
supported. A list of values can be given, in which case WireMock resolves the first file
|
||||
that exists when it needs to find a response body.</p>
|
||||
</div>
|
||||
<div class="admonitionblock note">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-note" title="Note"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
When you configure the <code>files</code> root, it also affects the
|
||||
automatic loading of stubs, because they come from the root location
|
||||
in a subdirectory called "mappings". The value of <code>files</code> has no
|
||||
effect on the stubs loaded explicitly from the <code>stubs</code> attribute.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_alternative_using_junit_rules"><a class="link" href="#_alternative_using_junit_rules">Alternative: Using JUnit Rules</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>For a more conventional WireMock experience, you can use JUnit <code>@Rules</code> to start and stop
|
||||
the server. To do so, use the <code>WireMockSpring</code> convenience class to obtain an <code>Options</code>
|
||||
instance, as shown in the following example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class WiremockForDocsClassRuleTests {
|
||||
|
||||
// Start WireMock on some dynamic port
|
||||
// for some reason `dynamicPort()` is not working properly
|
||||
@ClassRule
|
||||
public static WireMockClassRule wiremock = new WireMockClassRule(
|
||||
WireMockSpring.options().dynamicPort());
|
||||
|
||||
// A service that calls out over HTTP to wiremock's port
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.service.setBase("http://localhost:" + wiremock.port());
|
||||
}
|
||||
|
||||
// Using the WireMock APIs in the normal way:
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Stubbing WireMock
|
||||
wiremock.stubFor(get(urlEqualTo("/resource")).willReturn(aResponse()
|
||||
.withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>@ClassRule</code> means that the server shuts down after all the methods in this class
|
||||
have been run.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_relaxed_ssl_validation_for_rest_template"><a class="link" href="#_relaxed_ssl_validation_for_rest_template">Relaxed SSL Validation for Rest Template</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>WireMock lets you stub a "secure" server with an "https" URL protocol. If your
|
||||
application wants to contact that stub server in an integration test, it will find that
|
||||
the SSL certificates are not valid (the usual problem with self-installed certificates).
|
||||
The best option is often to re-configure the client to use "http". If that’s not an
|
||||
option, you can ask Spring to configure an HTTP client that ignores SSL validation errors
|
||||
(do so only for tests, of course).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To make this work with minimum fuss, you need to be using the Spring Boot
|
||||
<code>RestTemplateBuilder</code> in your app, as shown in the following example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
return builder.build();
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>You need <code>RestTemplateBuilder</code> because the builder is passed through callbacks to
|
||||
initialize it, so the SSL validation can be set up in the client at that point. This
|
||||
happens automatically in your test if you are using the <code>@AutoConfigureWireMock</code>
|
||||
annotation or the stub runner. If you use the JUnit <code>@Rule</code> approach, you need to add the
|
||||
<code>@AutoConfigureHttpClient</code> annotation as well, as shown in the following example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest("app.baseUrl=https://localhost:6443")
|
||||
@AutoConfigureHttpClient
|
||||
public class WiremockHttpsServerApplicationTests {
|
||||
|
||||
@ClassRule
|
||||
public static WireMockClassRule wiremock = new WireMockClassRule(
|
||||
WireMockSpring.options().httpsPort(6443));
|
||||
...
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you are using <code>spring-boot-starter-test</code>, you have the Apache HTTP client on the
|
||||
classpath and it is selected by the <code>RestTemplateBuilder</code> and configured to ignore SSL
|
||||
errors. If you use the default <code>java.net</code> client, you do not need the annotation (but it
|
||||
won’t do any harm). There is no support currently for other clients, but it may be added
|
||||
in future releases.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To disable the custom <code>RestTemplateBuilder</code>, set the <code>wiremock.rest-template-ssl-enabled</code>
|
||||
property to <code>false</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_wiremock_and_spring_mvc_mocks"><a class="link" href="#_wiremock_and_spring_mvc_mocks">WireMock and Spring MVC Mocks</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into
|
||||
a Spring <code>MockRestServiceServer</code>. The following code shows an example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
|
||||
public class WiremockForDocsMockServerApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// will read stubs classpath
|
||||
MockRestServiceServer server = WireMockRestServiceServer.with(this.restTemplate)
|
||||
.baseUrl("https://example.org").stubs("classpath:/stubs/resource.json")
|
||||
.build();
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World");
|
||||
server.verify();
|
||||
}
|
||||
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>baseUrl</code> value is prepended to all mock calls, and the <code>stubs()</code> method takes a stub
|
||||
path resource pattern as an argument. In the preceding example, the stub defined at
|
||||
<code>/stubs/resource.json</code> is loaded into the mock server. If the <code>RestTemplate</code> is asked to
|
||||
visit <code><a href="https://example.org/" class="bare">https://example.org/</a></code>, it gets the responses as being declared at that URL. More
|
||||
than one stub pattern can be specified, and each one can be a directory (for a recursive
|
||||
list of all ".json"), a fixed filename (as in the example above), or an Ant-style
|
||||
pattern. The JSON format is the normal WireMock format, which you can read about in the
|
||||
<a href="https://wiremock.org/docs/stubbing/">WireMock website</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Currently, the Spring Cloud Contract Verifier supports Tomcat, Jetty, and Undertow as
|
||||
Spring Boot embedded servers, and Wiremock itself has "native" support for a particular
|
||||
version of Jetty (currently 9.2). To use the native Jetty, you need to add the native
|
||||
Wiremock dependencies and exclude the Spring Boot container (if there is one).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_customization_of_wiremock_configuration"><a class="link" href="#_customization_of_wiremock_configuration">Customization of WireMock configuration</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>You can register a bean of <code>org.springframework.cloud.contract.wiremock.WireMockConfigurationCustomizer</code> type
|
||||
in order to customize the WireMock configuration (e.g. add custom transformers).
|
||||
Example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> @Bean
|
||||
WireMockConfigurationCustomizer optionsCustomizer() {
|
||||
return new WireMockConfigurationCustomizer() {
|
||||
@Override
|
||||
public void customize(WireMockConfiguration options) {
|
||||
// perform your customization here
|
||||
}
|
||||
};
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_generating_stubs_using_rest_docs"><a class="link" href="#_generating_stubs_using_rest_docs">Generating Stubs using REST Docs</a></h3>
|
||||
<div class="paragraph">
|
||||
<p><a href="https://projects.spring.io/spring-restdocs">Spring REST Docs</a> can be used to generate
|
||||
documentation (for example in Asciidoctor format) for an HTTP API with Spring MockMvc
|
||||
or <code>WebTestClient</code> or Rest Assured. At the same time that you generate documentation for your API, you can also
|
||||
generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your
|
||||
normal REST Docs test cases and use <code>@AutoConfigureRestDocs</code> to have stubs be
|
||||
automatically generated in the REST Docs output directory. The following code shows an
|
||||
example using <code>MockMvc</code>:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureRestDocs(outputDir = "target/snippets")
|
||||
@AutoConfigureMockMvc
|
||||
public class ApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
mockMvc.perform(get("/resource"))
|
||||
.andExpect(content().string("Hello World"))
|
||||
.andDo(document("resource"));
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This test generates a WireMock stub at "target/snippets/stubs/resource.json". It matches
|
||||
all GET requests to the "/resource" path. The same example with <code>WebTestClient</code> (used
|
||||
for testing Spring WebFlux applications) would look like this:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureRestDocs(outputDir = "target/snippets")
|
||||
@AutoConfigureWebTestClient
|
||||
public class ApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient client;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
client.get().uri("/resource").exchange()
|
||||
.expectBody(String.class).isEqualTo("Hello World")
|
||||
.consumeWith(document("resource"));
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Without any additional configuration, these tests create a stub with a request matcher
|
||||
for the HTTP method and all headers except "host" and "content-length". To match the
|
||||
request more precisely (for example, to match the body of a POST or PUT), we need to
|
||||
explicitly create a request matcher. Doing so has two effects:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Creating a stub that matches only in the way you specify.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Asserting that the request in the test case also matches the same conditions.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The main entry point for this feature is <code>WireMockRestDocs.verify()</code>, which can be used
|
||||
as a substitute for the <code>document()</code> convenience method, as shown in the following
|
||||
example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import static org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocs.verify;</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre>@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureRestDocs(outputDir = "target/snippets")
|
||||
@AutoConfigureMockMvc
|
||||
public class ApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
mockMvc.perform(post("/resource")
|
||||
.content("{\"id\":\"123456\",\"message\":\"Hello World\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(verify().jsonPath("$.id")
|
||||
.stub("resource"));
|
||||
}
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This contract specifies that any valid POST with an "id" field receives the response
|
||||
defined in this test. You can chain together calls to <code>.jsonPath()</code> to add additional
|
||||
matchers. If JSON Path is unfamiliar, The <a href="https://github.com/jayway/JsonPath">JayWay
|
||||
documentation</a> can help you get up to speed. The <code>WebTestClient</code> version of this test
|
||||
has a similar <code>verify()</code> static helper that you insert in the same place.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Instead of the <code>jsonPath</code> and <code>contentType</code> convenience methods, you can also use the
|
||||
WireMock APIs to verify that the request matches the created stub, as shown in the
|
||||
following example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Test
|
||||
public void contextLoads() throws Exception {
|
||||
mockMvc.perform(post("/resource")
|
||||
.content("{\"id\":\"123456\",\"message\":\"Hello World\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(verify()
|
||||
.wiremock(WireMock.post(
|
||||
urlPathEquals("/resource"))
|
||||
.withRequestBody(matchingJsonPath("$.id"))
|
||||
.stub("post-resource"));
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The WireMock API is rich. You can match headers, query parameters, and request body by
|
||||
regex as well as by JSON path. These features can be used to create stubs with a wider
|
||||
range of parameters. The above example generates a stub resembling the following example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="title">post-resource.json</div>
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-json hljs" data-lang="json">{
|
||||
"request" : {
|
||||
"url" : "/resource",
|
||||
"method" : "POST",
|
||||
"bodyPatterns" : [ {
|
||||
"matchesJsonPath" : "$.id"
|
||||
}]
|
||||
},
|
||||
"response" : {
|
||||
"status" : 200,
|
||||
"body" : "Hello World",
|
||||
"headers" : {
|
||||
"X-Application-Context" : "application:-1",
|
||||
"Content-Type" : "text/plain"
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admonitionblock note">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-note" title="Note"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
You can use either the <code>wiremock()</code> method or the <code>jsonPath()</code> and <code>contentType()</code>
|
||||
methods to create request matchers, but you can’t use both approaches.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>On the consumer side, you can make the <code>resource.json</code> generated earlier in this section
|
||||
available on the classpath (by
|
||||
<<publishing-stubs-as-jars], for example). After that, you can create a stub using WireMock in a
|
||||
number of different ways, including by using
|
||||
<code>@AutoConfigureWireMock(stubs="classpath:resource.json")</code>, as described earlier in this
|
||||
document.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_generating_contracts_by_using_rest_docs"><a class="link" href="#_generating_contracts_by_using_rest_docs">Generating Contracts by Using REST Docs</a></h3>
|
||||
<div class="paragraph">
|
||||
<p>You can also generate Spring Cloud Contract DSL files and documentation with Spring REST
|
||||
Docs. If you do so in combination with Spring Cloud WireMock, you get both the contracts
|
||||
and the stubs.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Why would you want to use this feature? Some people in the community asked questions
|
||||
about a situation in which they would like to move to DSL-based contract definition,
|
||||
but they already have a lot of Spring MVC tests. Using this feature lets you generate
|
||||
the contract files that you can later modify and move to folders (defined in your
|
||||
configuration) so that the plugin finds them.</p>
|
||||
</div>
|
||||
<div class="admonitionblock tip">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-tip" title="Tip"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
You might wonder why this functionality is in the WireMock module. The functionality
|
||||
is there because it makes sense to generate both the contracts and the stubs.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Consider the following test:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> this.mockMvc
|
||||
.perform(post("/foo").accept(MediaType.APPLICATION_PDF)
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"foo\": 23, \"bar\" : \"baz\" }"))
|
||||
.andExpect(status().isOk()).andExpect(content().string("bar"))
|
||||
// first WireMock
|
||||
.andDo(WireMockRestDocs.verify().jsonPath("$[?(@.foo >= 20)]")
|
||||
.jsonPath("$[?(@.bar in ['baz','bazz','bazzz'])]")
|
||||
.contentType(MediaType.valueOf("application/json"))
|
||||
.stub("shouldGrantABeerIfOldEnough"))
|
||||
// then Contract DSL documentation
|
||||
.andDo(document("index", SpringCloudContractRestDocs.dslContract()));</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The preceding test creates the stub presented in the previous section, generating both
|
||||
the contract and a documentation file.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The contract is called <code>index.groovy</code> and might look like the following example:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="highlightjs highlight"><code class="language-groovy hljs" data-lang="groovy">import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
Contract.make {
|
||||
request {
|
||||
method 'POST'
|
||||
url '/foo'
|
||||
body('''
|
||||
{"foo": 23 }
|
||||
''')
|
||||
headers {
|
||||
header('''Accept''', '''application/json''')
|
||||
header('''Content-Type''', '''application/json''')
|
||||
}
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
body('''
|
||||
bar
|
||||
''')
|
||||
headers {
|
||||
header('''Content-Type''', '''application/json;charset=UTF-8''')
|
||||
header('''Content-Length''', '''3''')
|
||||
}
|
||||
testMatchers {
|
||||
jsonPath('$[?(@.foo >= 20)]', byType())
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The generated document (formatted in Asciidoc in this case) contains a formatted
|
||||
contract. The location of this file would be <code>index/dsl-contract.adoc</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="js/tocbot/tocbot.min.js"></script>
|
||||
<script type="text/javascript" src="js/toc.js"></script>
|
||||
<link rel="stylesheet" href="js/highlight/styles/atom-one-dark-reasonable.min.css">
|
||||
<script src="js/highlight/highlight.min.js"></script>
|
||||
<script>hljs.initHighlighting()</script>
|
||||
</body>
|
||||
</html>
|
||||
If you are not redirected automatically, follow the <a href='https://spring.io/projects/spring-cloud-contract#learn'>link to docs</a>
|
||||
|
||||
Reference in New Issue
Block a user