diff --git a/_docs/request-matching.md b/_docs/request-matching.md index e9436568..553e2f38 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -25,8 +25,9 @@ you need more precise control: ## Request with XML Body -Code: +{% codetabs %} +{% codetab Java %} ```java stubFor(any(urlPathEqualTo("/everything")) .withHeader("Accept", containing("xml")) @@ -43,9 +44,9 @@ stubFor(any(urlPathEqualTo("/everything")) ) .willReturn(aResponse())); ``` +{% endcodetab %} -Configuration file: - +{% codetab JSON %} ```json { "request": { @@ -102,15 +103,23 @@ Configuration file: } } ``` +{% endcodetab %} + +{% endcodetabs %} ## Request with Form Parameters +{% codetabs %} + +{% codetab Java %} ```java stubFor(post(urlPathEqualTo("/mock")) .withFormParam("tool", equalTo("WireMock") ).willReturn(ok())); ``` +{% endcodetab %} +{% codetab JSON %} ```json { "request": { @@ -127,6 +136,9 @@ stubFor(post(urlPathEqualTo("/mock")) } } ``` +{% endcodetab %} + +{% endcodetabs %} The following sections describe each type of matching strategy in detail. @@ -138,14 +150,15 @@ It is usually preferable to match on path only if you want to match multiple que ### Equality matching on path and query -Java: +{% codetabs %} +{% codetab Java %} ```java urlEqualTo("/your/url?and=query") ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -155,17 +168,21 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Regex matching on path and query -Java: +{% codetabs %} +{% codetab Java %} ```java urlMatching("/your/([a-z]*)\\?and=query") ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -175,17 +192,21 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Equality matching on the path only -Java: +{% codetabs %} +{% codetab Java %} ```java urlPathEqualTo("/your/url") ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -195,17 +216,21 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Regex matching on the path only -Java: +{% codetabs %} +{% codetab Java %} ```java urlPathMatching("/your/([a-z]*)") ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -215,6 +240,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Path templates @@ -227,16 +255,17 @@ When the path template URL match type is used this enables To match any request URL that conforms to the path template, you can do the following. -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor( get(urlPathTemplate("/contacts/{contactId}/addresses/{addressId}")) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -248,9 +277,15 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} To further constrain the match to specific values of the path variables you can add match clauses for some or all of the variables in the path expression. +{% codetabs %} + +{% codetab Java %} ```java stubFor( get(urlPathTemplate("/contacts/{contactId}/addresses/{addressId}")) @@ -258,9 +293,9 @@ stubFor( .withPathParam("addressId", equalTo("99876")) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request" : { @@ -280,7 +315,9 @@ JSON: } } ``` +{% endcodetab %} +{% endcodetabs %} ## Matching other attributes @@ -290,14 +327,15 @@ All request attributes other than the URL can be matched using the following set Deems a match if the entire attribute value equals the expected value. -Java: +{% codetabs %} +{% codetab Java %} ```java .withHeader("Content-Type", equalTo("application/json")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -312,19 +350,23 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Case-insensitive equality Deems a match if the entire attribute value equals the expected value, ignoring case. -Java: +{% codetabs %} +{% codetab Java %} ```java .withHeader("Content-Type", equalToIgnoreCase("application/json")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -340,13 +382,17 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Binary Equality Deems a match if the entire binary attribute value equals the expected value. Unlike the above equalTo operator, this compares byte arrays (or their equivalent base64 representation). -Java: +{% codetabs %} +{% codetab Java %} ```java // Specifying the expected value as a byte array .withRequestBody(binaryEqualTo(new byte[] { 1, 2, 3 })) @@ -354,9 +400,9 @@ Java: // Specifying the expected value as a base64 String .withRequestBody(binaryEqualTo("AQID")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -369,19 +415,23 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Substring (contains) Deems a match if the a portion of the attribute value equals the expected value. -Java: +{% codetabs %} +{% codetab Java %} ```java .withCookie("my_profile", containing("johnsmith@example.com")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -396,19 +446,23 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Negative substring (does not contain) Deems a match if the attribute value does not contain the expected value. -Java: +{% codetabs %} +{% codetab Java %} ```java .withCookie("my_profile", notContaining("johnsmith@example.com")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -423,19 +477,23 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Regular expression Deems a match if the entire attribute value matched the expected regular expression. -Java: +{% codetabs %} +{% codetab Java %} ```java .withQueryParam("search_term", matching("^(.*)wiremock([A-Za-z]+)$")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -450,17 +508,21 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} It is also possible to perform a negative match i.e. the match succeeds when the attribute value does not match the regex: -Java: +{% codetabs %} +{% codetab Java %} ```java .withQueryParam("search_term", notMatching("^(.*)wiremock([A-Za-z]+)$")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -475,19 +537,23 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### JSON equality Deems a match if the attribute (most likely the request body in practice) is valid JSON and is a semantic match for the expected value. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(equalToJson("{ \"total_results\": 4 }")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -500,9 +566,15 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} -JSON with string literal: +With string literal: +{% codetabs %} + +{% codetab JSON %} ```json { "request": { @@ -515,19 +587,23 @@ JSON with string literal: ... } ``` +{% endcodetab %} + +{% endcodetabs %} #### Less strict matching By default different array orderings and additional object attributes will trigger a non-match. However, both of these conditions can be disabled individually. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(equalToJson("{ \"total_results\": 4 }", true, true)) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -542,6 +618,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} #### Placeholders @@ -571,14 +650,15 @@ Deems a match if the attribute value is valid JSON and matches the [JSON Path](h Deems a match if the attribute value is present in the JSON. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingJsonPath("$.name")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -591,6 +671,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} Request body example: @@ -605,14 +688,15 @@ Request body example: Deems a match if the attribute value equals the expected value. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingJsonPath("$.things[?(@.name == 'RequiredThing')]")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -625,6 +709,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} Request body example: @@ -641,14 +728,15 @@ Request body example: Deems a match if the attribute value matches the regex expected value. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingJsonPath("$.things[?(@.name =~ /Required.*/i)]")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -661,6 +749,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} Request body example: @@ -678,14 +769,15 @@ Request body example: Deems a match if the attribute size matches the expected size. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingJsonPath("$[?(@.things.size() == 2)]")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -698,6 +790,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} Request body example: @@ -712,14 +807,15 @@ Request body example: The JSONPath matcher can be combined with another matcher, such that the value returned from the JSONPath query is evaluated against it: -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingJsonPath("$..todoItem", containing("wash"))) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -735,6 +831,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} Since WireMock's matching operators all work on strings, the value selected by the JSONPath expression will be coerced to a string before the match is evaluated. This true even if the returned value is an object or array. A benefit of this is that this allows a sub-document to be selected using JSONPath, then matched using the `equalToJson` operator. E.g. for the following request body: @@ -749,14 +848,17 @@ is an object or array. A benefit of this is that this allows a sub-document to b The following will match: +{% codetabs %} + +{% codetab Java %} ```java .withRequestBody(matchingJsonPath("$.outer", equalToJson("{ \n" + " \"inner\": 42 \n" + "}"))) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -772,6 +874,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### JSON schema @@ -779,8 +884,9 @@ Deems a match if the value conforms to the expected JSON schema. By default the [V202012](https://json-schema.org/draft/2020-12/schema){:target="{{site.data.misc.blank}}"} version of the JSON schema spec will be used, but this can be changed to one of `V4`, `V6`, `V7`, `V201909`, `V202012` via the `schemaVersion` parameter. -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor( post(urlPathEqualTo("/schema-match")) @@ -800,9 +906,10 @@ stubFor( "}")) .willReturn(ok())); ``` +{% endcodetab %} -JSON (supported in 3.4+): - +{% codetab JSON %} +(supported in 3.4+): ```json { "request" : { @@ -831,8 +938,15 @@ JSON (supported in 3.4+): } } ``` +{% endcodetab %} + +{% endcodetabs %} + +With string literal: -JSON with string literal: +{% codetabs %} + +{% codetab JSON %} ```json { @@ -849,20 +963,23 @@ JSON with string literal: } } ``` +{% endcodetab %} +{% endcodetabs %} ### XML equality Deems a match if the attribute value is valid XML and is semantically equal to the expected XML document. The underlying engine for determining XML equality is [XMLUnit](http://www.xmlunit.org/). -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(equalToXml("Hello")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -875,21 +992,25 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} #### Use of placeholders The XMLUnit [placeholders](https://github.com/xmlunit/user-guide/wiki/Placeholders) feature is supported in WireMock. For example, when comparing the XML documents, you can ignore some text nodes. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody( equalToXml("${xmlunit.ignore}Hello", true) ) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -903,13 +1024,17 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} When the actual request body is `123456Hello`, it will be deemed a match. -If the default placeholder delimiters `${` and `}` can not be used, you can specify custom delimiters (using regular expressions). For example +If the default placeholder delimiters `${` and `}` can not be used, you can specify custom delimiters (using regular expressions). For example: -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody( equalToXml("[[xmlunit.ignore]]Hello", @@ -919,9 +1044,9 @@ Java: ) ) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -937,13 +1062,17 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} #### Excluding specific types of comparison You can further tune how XML documents are compared for equality by disabling specific [XMLUnit comparison types](https://www.xmlunit.org/api/java/2.7.0/org/xmlunit/diff/ComparisonType.html). -Java: +{% codetabs %} +{% codetab Java %} ```java import static org.xmlunit.diff.ComparisonType.*; @@ -953,9 +1082,9 @@ import static org.xmlunit.diff.ComparisonType.*; .exemptingComparisons(NAMESPACE_URI, ELEMENT_TAG_NAME) ) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -969,6 +1098,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} The full list of comparison types used by default is as follows: @@ -990,14 +1122,18 @@ The full list of comparison types used by default is as follows: By default, WireMock takes into account an order of identical child nodes. Meaning if actual request has different order of same node on same level than stub it won't be matched. As of WireMock version `3.7.0`, this can be changed by passing additional argument to the `equalToXml` method -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(equalToXml("" + " 1" + " 2" + "",false,true)) ``` +{% endcodetab %} + +{% codetab JSON %} ```json { "request": { @@ -1011,6 +1147,10 @@ Java: ... } ``` +{% endcodetab %} + +{% endcodetabs %} + This will make sure that stub above matches both of following requests: ```xml @@ -1030,14 +1170,15 @@ If third argument is passed as `false` then first xml will not match the stub Deems a match if the attribute value is valid XML and matches the XPath expression supplied. An XML document will be considered to match if any elements are returned by the XPath evaluation. WireMock delegates to Java's in-built XPath engine (via XMLUnit), therefore up to (at least) Java 8 it supports XPath version 1.0. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingXPath("/todo-list[count(todo-item) = 3]")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1050,22 +1191,26 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} The above example will select elements based on their local name if used with a namespaced XML document. If you need to be able to select elements based on their namespace in addition to their name you can declare the prefix to namespace URI mappings and use them in your XPath expression: -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingXPath("/stuff:outer/more:inner[.=111]") .withXPathNamespace("stuff", "http://stuff.example.com") .withXPathNamespace("more", "http://more.example.com")) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1082,19 +1227,23 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} #### Nested value matching The XPath matcher described above can be combined with another matcher, such that the value returned from the XPath query is evaluated against it: -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingXPath("//todo-item/text()", containing("wash"))) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1110,20 +1259,24 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} If multiple nodes are returned from the XPath query, all will be evaluated and the returned match will be the one with the shortest distance. If the XPath expression returns an XML element rather than a value, this will be rendered as an XML string before it is passed to the value matcher. This can be usefully combined with the `equalToXml` matcher e.g. -Java: +{% codetabs %} +{% codetab Java %} ```java .withRequestBody(matchingXPath("//todo-item", equalToXml("Do the washing"))) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1139,21 +1292,25 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ### Absence Deems a match if the attribute specified is absent from the request. -Java: +{% codetabs %} +{% codetab Java %} ```java .withCookie("session", absent()) .withQueryParam("search_term", absent()) .withHeader("X-Absent", absent()) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1178,14 +1335,18 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ## Multipart/form-data Deems a match if a multipart value is valid and matches any or all the multipart pattern matchers supplied. As a Multipart is a 'mini' HTTP request in itself all existing Header and Body content matchers can by applied to a Multipart pattern. A Multipart pattern can be defined as matching `ANY` request multiparts or `ALL`. The default matching type is `ANY`. -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(...) ... @@ -1196,9 +1357,9 @@ stubFor(...) .withMultipartBody(equalToJson("{}")) ) ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1222,6 +1383,9 @@ JSON: ... } ``` +{% endcodetab %} + +{% endcodetabs %} ## Basic Authentication @@ -1229,14 +1393,15 @@ Although matching on HTTP basic authentication could be supported via a correctly encoded `Authorization` header, you can also do this more simply via the API. -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(get(urlEqualTo("/basic-auth")).withBasicAuth("user", "pass") ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1252,6 +1417,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} ## Dates and times @@ -1265,8 +1433,9 @@ actual dates can be truncated in various ways. You can match an incoming date/time against a fixed value e.g. "match if the X-Munged-Date request header is after x": -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(post("/dates") .withHeader("X-Munged-Date", after("2021-05-01T00:00:00Z")) @@ -1277,9 +1446,9 @@ stubFor(post("/dates") .withHeader("X-Munged-Date", after(ZonedDateTime.parse("2021-05-01T00:00:00Z"))) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1296,22 +1465,26 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} ### Offset You can also match in incoming value against the current date/time or an offset from it: -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(post("/dates") .withHeader("X-Munged-Date", beforeNow().expectedOffset(3, DateTimeUnit.DAYS)) .withHeader("X-Finalised-Date", before("now +2 months")) // This form and beforeNow() are equivalent .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1331,6 +1504,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} ### Local vs. Zoned @@ -1357,17 +1533,18 @@ HTTP RFCs 1123, 1036 and asctime (taken from C but also valid for specifying HTT It is also possible to specify your own format using [Java's date format strings](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns). -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(post("/dates") .withHeader("X-Munged-Date", equalToDateTime("2021-06-24T00:00:00").actualFormat("dd/MM/yyyy")) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1382,6 +1559,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} ### Truncation @@ -1393,8 +1573,9 @@ Truncation is useful if you want to create expressions like "before the end of t It can usefully be combined with offsetting so e.g. if the match required is "after the 15th of this month" we could do as follows. -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(post("/dates") .withRequestBody(matchingJsonPath( @@ -1403,9 +1584,9 @@ stubFor(post("/dates") ) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1423,9 +1604,15 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} Truncating the actual value can be useful when checking for equality with literal date/times e.g. to say "is in March 2020": +{% codetabs %} + +{% codetab Java %} ```java stubFor(post("/dates") .withRequestBody(matchingJsonPath( @@ -1434,9 +1621,9 @@ stubFor(post("/dates") ) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1454,6 +1641,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %}
The full list of available truncations is: @@ -1471,16 +1661,17 @@ The full list of available truncations is: By default, the date/time truncation is applied first and the offset is applied afterwards. There are scenarios, though, where the order needs to be reversed. For instance, if we want to match with the last day of the next month then the truncation should be applied last. In this case the boolean property `applyTruncationLast` should be set to true: -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(get(urlPathEqualTo("/resource")) .withQueryParam("date", equalToDateTime("now +1 months").truncateExpected(LAST_DAY_OF_MONTH).applyTruncationLast(true)) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1496,6 +1687,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} In the example above setting the `applyTruncationLast` property to true means that the expected date/time value will first be offset by one month and only afterwards truncated to the last day of that month. Which in turn means that if the current date is September 1st then the expected date will first be offset to October 1st and only then truncated to October 31st. Had the `applyTruncationLast` property been false (the default value) then the resulting expected date would be October 30th, one day off the date we were aiming for. @@ -1503,8 +1697,9 @@ In the example above setting the `applyTruncationLast` property to true means th You can combine two or more matchers in an AND expression. -Java: +{% codetabs %} +{% codetab Java %} ```java // Both statements are equivalent @@ -1519,9 +1714,9 @@ stubFor(get(urlPathEqualTo("/and")) .withHeader("X-Some-Value", matching("[a-z]+").and(containing("magicvalue"))) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1542,11 +1737,15 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} Similarly you can also construct an OR expression. -Java: +{% codetabs %} +{% codetab Java %} ```java // Both statements are equivalent @@ -1561,9 +1760,9 @@ stubFor(get(urlPathEqualTo("/or")) .withQueryParam("search", matching("[a-z]+").or(absent())) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1584,6 +1783,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} ### Combining date matchers as JSONPath/XPath sub-matchers @@ -1593,8 +1795,9 @@ is a date/time between two points. We can do this by extracting the field using `matchesJsonPath` then matching the result of this against the `before` and `after` matchers AND'd together. -Java: +{% codetabs %} +{% codetab Java %} ```java stubFor(post("/date-range") .withRequestBody(matchingJsonPath("$.date", @@ -1602,9 +1805,9 @@ stubFor(post("/date-range") after("2020-01-01T00:00:00")))) .willReturn(ok())); ``` +{% endcodetab %} -JSON: - +{% codetab JSON %} ```json { "request": { @@ -1628,6 +1831,9 @@ JSON: } } ``` +{% endcodetab %} + +{% endcodetabs %} This would match the following JSON request body: @@ -1643,13 +1849,19 @@ You can match multiple values of a query parameter or header with below provided Exactly matcher exactly matches multiple values or patterns and make sure that it does not contain any other value. +There must be 3 values of id exactly whose values are 1, 2, and 3: + +{% codetabs %} + +{% codetab Java %} ```java -// There must be 3 values of id exactly whose values are 1, 2, and 3 stubFor(get(urlPathEqualTo("/things")) .withQueryParam("id", havingExactly("1", "2", "3")) .willReturn(ok())); ``` +{% endcodetab %} +{% codetab JSON %} ```json { "mapping": { @@ -1678,9 +1890,16 @@ stubFor(get(urlPathEqualTo("/things")) } } ``` +{% endcodetab %} + +{% endcodetabs %} + +There must be 3 values of id exactly whose values conform to the match expressions +{% codetabs %} + +{% codetab Java %} ```java -// There must be 3 values of id exactly whose values conform to the match expressions stubFor(get(urlPathEqualTo("/things")) .withQueryParam("id", havingExactly( equalTo("1"), @@ -1688,7 +1907,9 @@ stubFor(get(urlPathEqualTo("/things")) notContaining("3") )).willReturn(ok())); ``` +{% endcodetab %} +{% codetab JSON %} ```json { "mapping": { @@ -1717,16 +1938,26 @@ stubFor(get(urlPathEqualTo("/things")) } } ``` +{% endcodetab %} + +{% endcodetabs %} Includes matcher matches multiple values or patterns specified and may contain other values as well. +The values of id must include 1, 2, and 3: + +{% codetabs %} + +{% codetab Java %} ```java -// The values of id must include 1, 2, and 3. stubFor(get(urlPathEqualTo("/things")) .withQueryParam("id", including("1", "2", "3")) .willReturn(ok())); ``` +{% endcodetab %} + +{% codetab JSON %} ```json { "mapping": { @@ -1755,9 +1986,16 @@ stubFor(get(urlPathEqualTo("/things")) } } ``` +{% endcodetab %} + +{% endcodetabs %} +Values of id must conform to the match expressions: + +{% codetabs %} + +{% codetab Java %} ```java -//values of id must conform to the match expressions stubFor(get(urlPathEqualTo("/things")) .withQueryParam("id", including( equalTo("1"), @@ -1765,7 +2003,9 @@ stubFor(get(urlPathEqualTo("/things")) notContaining("3") )).willReturn(ok())); ``` +{% endcodetab %} +{% codetab JSON %} ```json { "mapping": { @@ -1794,3 +2034,6 @@ stubFor(get(urlPathEqualTo("/things")) } } ``` +{% endcodetab %} + +{% endcodetabs %}