Sync docs from master to gh-pages

This commit is contained in:
buildmaster
2017-01-10 16:35:38 +00:00
parent 516b27086a
commit 54f66b6d9d

View File

@@ -755,11 +755,16 @@ $(addBlockSwitches);
<li><a href="#_http_top_level_elements">HTTP Top-Level Elements</a></li>
<li><a href="#_request">Request</a></li>
<li><a href="#_response">Response</a></li>
<li><a href="#_dynamic_properties">Dynamic properties</a></li>
<li><a href="#_dynamic_properties">Dynamic properties</a>
<ul class="sectlevel4">
<li><a href="#_dynamic_properties_inside_the_body">Dynamic properties inside the body</a>
<ul class="sectlevel5">
<li><a href="#_regular_expressions">Regular expressions</a></li>
<li><a href="#_passing_optional_parameters">Passing optional parameters</a></li>
<li><a href="#_executing_custom_methods_on_server_side">Executing custom methods on server side</a>
<ul class="sectlevel4">
<li><a href="#_executing_custom_methods_on_server_side">Executing custom methods on server side</a></li>
</ul>
</li>
<li><a href="#_dynamic_properties_in_matchers_sections">Dynamic properties in matchers sections</a></li>
<li><a href="#_contract_dsl_2">Contract DSL</a></li>
<li><a href="#_base_mock_spec">Base Mock Spec</a></li>
</ul>
@@ -6391,10 +6396,13 @@ or just set the <code>ignored</code> property on the contract itself:</p>
<div class="paragraph">
<p>The contract can contain some dynamic properties - timestamps / ids etc. You don&#8217;t want to enforce the consumers to stub their
clocks to always return the same value of time so that it gets matched by the stub. That&#8217;s why we allow you to provide the dynamic
parts in your contracts in the following way</p>
parts in your contracts in two ways. One is to pass them directly in the
body and one to set them in a separate section called <code>testMatchers</code> and <code>stubMatchers</code>.</p>
</div>
<div class="sect4">
<h5 id="_dynamic_properties_inside_the_body">Dynamic properties inside the body</h5>
<div class="paragraph">
<p>either via the <code>value</code> method</p>
<p>You can set the properties inside the body either via the <code>value</code> method</p>
</div>
<div class="listingblock">
<div class="content">
@@ -6419,9 +6427,8 @@ $(client(...), server(...))</code></pre>
<p>All of the aforementioned approaches are equal. That means that <code>stub</code> and <code>client</code> methods are aliases over the <code>consumer</code>
method. Let&#8217;s take a closer look at what we can do with those values in the subsequent sections.</p>
</div>
</div>
<div class="sect3">
<h4 id="_regular_expressions">Regular expressions</h4>
<div class="sect5">
<h6 id="_regular_expressions">Regular expressions</h6>
<div class="paragraph">
<p>You can use regular expressions to write your requests in Contract DSL. It is particularly useful when you want to indicate that a given response
should be provided for requests that follow a given pattern. Also, you can use it when you need to use patterns and not exact values both
@@ -6584,8 +6591,8 @@ String isoTime() {
</div>
</div>
</div>
<div class="sect3">
<h4 id="_passing_optional_parameters">Passing optional parameters</h4>
<div class="sect5">
<h6 id="_passing_optional_parameters">Passing optional parameters</h6>
<div class="paragraph">
<p>It is possible to provide optional parameters in your contract. It&#8217;s only possible to have optional parameter for the:</p>
</div>
@@ -6690,12 +6697,290 @@ String isoTime() {
</div>
</div>
</div>
<div class="sect3">
<h4 id="_executing_custom_methods_on_server_side">Executing custom methods on server side</h4>
<div class="sect5">
<h6 id="_executing_custom_methods_on_server_side">Executing custom methods on server side</h6>
<div class="paragraph">
<p>It is also possible to define a method call to be executed on the server side during the test. Such a method can be added to the class defined as "baseClassForTests"
in the configuration. Please see the examples below:</p>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_dynamic_properties_in_matchers_sections">Dynamic properties in matchers sections</h5>
<div class="paragraph">
<p>If you&#8217;ve been working with <a href="https://docs.pact.io/">Pact</a> this might seem familiar. Quite a few users
are used to having a separation between the body and setting dynamic parts of your contract.</p>
</div>
<div class="paragraph">
<p>That&#8217;s why you can profit from two separate sections. One is called <code>stubMatchers</code> where you can
define the dynamic values that should end up in a stub. You can set it in the <code>request</code> or <code>inputMessage</code>
part of your contract. The other is called <code>testMatchers</code> which is present in the <code>response</code> or
<code>outputMessage</code> side of the contract.</p>
</div>
<div class="paragraph">
<p>Currently we support only JSON Path based matchers with the following matching possibilities.
For <code>stubMatchers</code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>byRegex(&#8230;&#8203;)</code> - the value taken from the response via the provided JSON Path needs
to match the regex</p>
</li>
<li>
<p><code>byDate()</code> - the value taken from the response via the provided JSON Path needs to
match the regex for ISO Date</p>
</li>
<li>
<p><code>byTimestamp()</code> - the value taken from the response via the provided JSON Path needs
to match the regex for ISO DateTime</p>
</li>
<li>
<p><code>byTime()</code> - the value taken from the response via the provided JSON Path needs to
match the regex for ISO Time</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For <code>testMatchers</code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>byRegex(&#8230;&#8203;)</code> - the value taken from the response via the provided JSON Path needs
to match the regex</p>
</li>
<li>
<p><code>byDate()</code> - the value taken from the response via the provided JSON Path needs to
match the regex for ISO Date</p>
</li>
<li>
<p><code>byTimestamp()</code> - the value taken from the response via the provided JSON Path needs
to match the regex for ISO DateTime</p>
</li>
<li>
<p><code>byTime()</code> - the value taken from the response via the provided JSON Path needs to
match the regex for ISO Time</p>
</li>
<li>
<p><code>byType()</code> - the value taken from the 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>byType</code> can take a closure where you can set <code>minOccurrence</code> and <code>maxOccurrence</code>.
That way you can assert on the size of the collection.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Let&#8217;s take a look at the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">Contract contractDsl = Contract.make {
request {
method 'GET'
urlPath '/get'
body([
duck: 123,
alpha: "abc",
number: 123,
aBoolean: true,
date: "2017-01-01",
dateTime: "2017-01-01T01:23:45",
time: "01:02:34",
valueWithoutAMatcher: "foo",
valueWithTypeMatch: "string"
])
stubMatchers {
jsonPath('$.duck', byRegex("[0-9]{3}"))
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
jsonPath('$.number', byRegex(number()))
jsonPath('$.aBoolean', byRegex(anyBoolean()))
jsonPath('$.date', byDate())
jsonPath('$.dateTime', byTimestamp())
jsonPath('$.time', byTime())
}
headers {
contentType(applicationJson())
}
}
response {
status 200
body([
duck: 123,
alpha: "abc",
number: 123,
aBoolean: true,
date: "2017-01-01",
dateTime: "2017-01-01T01:23:45",
time: "01:02:34",
valueWithoutAMatcher: "foo",
valueWithTypeMatch: "string",
valueWithMin: [
1,2,3
],
valueWithMax: [
1,2,3
],
valueWithMinMax: [
1,2,3
],
])
testMatchers {
// asserts the jsonpath value against manual regex
jsonPath('$.duck', byRegex("[0-9]{3}"))
// asserts the jsonpath value against some default regex
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
jsonPath('$.number', byRegex(number()))
jsonPath('$.aBoolean', byRegex(anyBoolean()))
// asserts vs inbuilt time related regex
jsonPath('$.date', byDate())
jsonPath('$.dateTime', byTimestamp())
jsonPath('$.time', byTime())
// asserts that the resulting type is the same as in response body
jsonPath('$.valueWithTypeMatch', byType())
jsonPath('$.valueWithMin', byType {
// results in verification of size of array (min 1)
minOccurrence(1)
})
jsonPath('$.valueWithMax', byType {
// results in verification of size of array (max 3)
maxOccurrence(3)
})
jsonPath('$.valueWithMinMax', byType {
// results in verification of size of array (min 1 &amp; max 3)
minOccurrence(1)
maxOccurrence(3)
})
}
headers {
contentType(applicationJson())
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this example we&#8217;re providing the dynamic portions of the contract in the matchers sections.
For the request part you can see that for all fields but <code>valueWithoutAMatcher</code> we&#8217;re setting
explicitly the values of regular expressions we&#8217;d like the stub to contain. For the <code>valueWithoutAMatcher</code>
the verification will take place in the same way as without the usage of matchers - the test
will perform an equality check in this case.</p>
</div>
<div class="paragraph">
<p>For the response side in the <code>testMatchers</code> section we&#8217;re defining all the dynamic parts
in a similar manner. The only difference is that we have the <code>byType</code> matchers too. In that
case we&#8217;re checking 4 fields in the way that we&#8217;re verifying whether the response from the test
has a value whose JSON path matching the given field is of the same type as the one defined in the response body and:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>for <code>$.valueWithTypeMatch</code> - we&#8217;re just checking the whether the type is the same</p>
</li>
<li>
<p>for <code>$.valueWithMin</code> - we&#8217;re checking the type and assert if the size is greater or equal to the min occurrence</p>
</li>
<li>
<p>for <code>$.valueWithMax</code> - we&#8217;re checking the type and assert if the size is smaller or equal to the max occurrence</p>
</li>
<li>
<p>for <code>$.valueWithMinMax</code> - we&#8217;re checking the type and assert if the size is between the min and max occurrence</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The resulting test would look more or less like this (note that we&#8217;re separating the autogenerated
assertions and the one from matchers with an <code>and</code> section):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// given:
MockMvcRequestSpecification request = given()
.header("Content-Type", "application/json")
.body("{\"duck\":123,\"alpha\":\"abc\",\"number\":123,\"aBoolean\":true,\"date\":\"2017-01-01\",\"dateTime\":\"2017-01-01T01:23:45\",\"time\":\"01:02:34\",\"valueWithoutAMatcher\":\"foo\",\"valueWithTypeMatch\":\"string\"}");
// when:
ResponseOptions response = given().spec(request)
.get("/get");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).matches("application/json.*");
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field("valueWithoutAMatcher").isEqualTo("foo");
// and:
assertThat(parsedJson.read("$.duck", String.class)).matches("[0-9]{3}");
assertThat(parsedJson.read("$.alpha", String.class)).matches("[\\p{L}]*");
assertThat(parsedJson.read("$.number", String.class)).matches("-?\\d*(\\.\\d+)?");
assertThat(parsedJson.read("$.aBoolean", String.class)).matches("(true|false)");
assertThat(parsedJson.read("$.date", String.class)).matches("(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])");
assertThat(parsedJson.read("$.dateTime", String.class)).matches("([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])");
assertThat(parsedJson.read("$.time", String.class)).matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])");
assertThat((Object) parsedJson.read("$.valueWithTypeMatch")).isInstanceOf(class java.lang.String.class);
assertThat((Object) parsedJson.read("$.valueWithMin")).isInstanceOf(java.util.List.class);
assertThat(parsedJson.read("$.valueWithMin", java.util.Collection.class).size()).isLessThanOrEqualTo(1);
assertThat((Object) parsedJson.read("$.valueWithMax")).isInstanceOf(java.util.List.class);
assertThat(parsedJson.read("$.valueWithMax", java.util.Collection.class).size()).isGreaterThanOrEqualTo(3);
assertThat((Object) parsedJson.read("$.valueWithMinMax")).isInstanceOf(java.util.List.class);
assertThat(parsedJson.read("$.valueWithMinMax", java.util.Collection.class).size()).isStrictlyBetween(1, 3);</code></pre>
</div>
</div>
<div class="paragraph">
<p>and the WireMock stub like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-json" data-lang="json"> '''
{
"request" : {
"urlPath" : "/get",
"method" : "GET",
"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" : "$[?(@.alpha =~ /([\\\\p{L}]*)/)]"
}, {
"matchesJsonPath" : "$[?(@.number =~ /(-?\\\\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 =~ /(.*)/)]"
} ]
},
"response" : {
"status" : 200,
"body" : "{\\"duck\\":123,\\"alpha\\":\\"abc\\",\\"number\\":123,\\"aBoolean\\":true,\\"date\\":\\"2017-01-01\\",\\"dateTime\\":\\"2017-01-01T01:23:45\\",\\"time\\":\\"01:02:34\\",\\"valueWithoutAMatcher\\":\\"foo\\",\\"valueWithTypeMatch\\":\\"string\\",\\"valueWithMin\\":[1,2,3],\\"valueWithMax\\":[1,2,3],\\"valueWithMinMax\\":[1,2,3]}",
"headers" : {
"Content-Type" : "application/json"
}
}
}
'''</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_contract_dsl_2">Contract DSL</h5>
<div class="listingblock">