diff --git a/spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java b/spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java index d4c164dddd54..a61189199251 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java @@ -23,7 +23,6 @@ import javax.xml.xpath.XPathExpressionException; import org.hamcrest.Matcher; -import org.hamcrest.Matchers; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; @@ -48,6 +47,7 @@ * @author Craig Walls * @author Rossen Stoyanchev * @author Sam Brannen + * @author Simon Baslé * @since 3.2 */ public abstract class MockRestRequestMatchers { @@ -113,13 +113,49 @@ public static RequestMatcher requestTo(URI uri) { return request -> assertEquals("Unexpected request", uri, request.getURI()); } + /** + * Assert request query parameter values with the given Hamcrest matcher, + * matching on the entire {@link List} of values. + *

For example, this can be used to check that the list of query parameter + * values has at least one value matching a given Hamcrest matcher (such as + * {@link org.hamcrest.Matchers#hasItem(Matcher)}), that every value in the list + * matches common criteria (such as {@link org.hamcrest.Matchers#everyItem(Matcher)}), + * that each value in the list matches corresponding dedicated criteria + * (such as {@link org.hamcrest.Matchers#contains(Matcher[])}, etc. + * @param name the name of the query parameter whose value(s) will be asserted + * @param matcher the Hamcrest matcher to apply to the entire list of values + * for the given query parameter + * @since 5.3.26 + * @see #queryParam(String, Matcher...) + * @see #queryParam(String, String...) + */ + public static RequestMatcher queryParam(String name, Matcher> matcher) { + return request -> { + MultiValueMap params = getQueryParams(request); + List paramValues = params.get(name); + if (paramValues == null) { + fail("Expected query param <" + name + "> to exist but was null"); + } + assertThat("Query param [" + name + "] values", paramValues, matcher); + }; + } + /** * Assert request query parameter values with the given Hamcrest matcher(s). - *

Note that if the queryParam value list is larger than the number of provided - * {@code matchers}, extra values are considered acceptable. - * See {@link #queryParam(String, Matcher)} for a variant that takes a - * {@code Matcher} over the whole list of values. + *

If the query parameter value list is larger than the number of provided + * {@code matchers}, no matchers will be applied to the extra query parameter + * values, effectively ignoring the additional parameter values. If the number + * of provided {@code matchers} exceeds the number of query parameter values, + * an {@link AssertionError} will be thrown to signal the mismatch. + *

See {@link #queryParam(String, Matcher)} for a variant which accepts a + * {@code Matcher} that applies to the entire list of values as opposed to + * applying only to individual values. + * @param name the name of the query parameter whose value(s) will be asserted + * @param matchers the Hamcrest matchers to apply to individual query parameter + * values; the nth matcher is applied to the nth query + * parameter value * @see #queryParam(String, Matcher) + * @see #queryParam(String, String...) */ @SafeVarargs public static RequestMatcher queryParam(String name, Matcher... matchers) { @@ -134,11 +170,20 @@ public static RequestMatcher queryParam(String name, Matcher... /** * Assert request query parameter values. - *

Note that if the queryParam value list is larger than {@code expectedValues}, - * extra values are considered acceptable. - * See {@link #queryParam(String, Matcher)} for a variant that takes a - * {@code Matcher} over the whole list of values. + *

If the query parameter value list is larger than the number of + * {@code expectedValues}, no assertions will be applied to the extra query + * parameter values, effectively ignoring the additional parameter values. If + * the number of {@code expectedValues} exceeds the number of query parameter + * values, an {@link AssertionError} will be thrown to signal the mismatch. + *

See {@link #queryParam(String, Matcher)} for a variant which accepts a + * Hamcrest {@code Matcher} that applies to the entire list of values as opposed + * to asserting only individual values. + * @param name the name of the query parameter whose value(s) will be asserted + * @param expectedValues the expected values of individual query parameter values; + * the nth expected value is compared to the nth query + * parameter value * @see #queryParam(String, Matcher) + * @see #queryParam(String, Matcher...) */ public static RequestMatcher queryParam(String name, String... expectedValues) { return request -> { @@ -150,53 +195,51 @@ public static RequestMatcher queryParam(String name, String... expectedValues) { }; } + private static MultiValueMap getQueryParams(ClientHttpRequest request) { + return UriComponentsBuilder.fromUri(request.getURI()).build().getQueryParams(); + } + /** - * Assert request query parameter, matching on the whole {@code List} of values. - *

This can be used to check that the list has at least one value matching a - * criteria ({@link Matchers#hasItem(Matcher)}), or that every value in the list - * matches a common criteria ({@link Matchers#everyItem(Matcher)}), or that each - * value in the list matches its corresponding dedicated criteria - * ({@link Matchers#contains(Matcher[])}, and more. - * @param name the name of the query parameter to consider - * @param matcher the matcher to apply to the whole list of values for that header + * Assert request header values with the given Hamcrest matcher, matching on + * the entire {@link List} of values. + *

For example, this can be used to check that the list of header values + * has at least one value matching a given Hamcrest matcher (such as + * {@link org.hamcrest.Matchers#hasItem(Matcher)}), that every value in the list + * matches common criteria (such as {@link org.hamcrest.Matchers#everyItem(Matcher)}), + * that each value in the list matches corresponding dedicated criteria + * (such as {@link org.hamcrest.Matchers#contains(Matcher[])}, etc. + * @param name the name of the header whose value(s) will be asserted + * @param matcher the Hamcrest matcher to apply to the entire list of values + * for the given header * @since 5.3.26 + * @see #header(String, Matcher...) + * @see #header(String, String...) */ - public static RequestMatcher queryParam(String name, Matcher> matcher) { + public static RequestMatcher header(String name, Matcher> matcher) { return request -> { - MultiValueMap params = getQueryParams(request); - List paramValues = params.get(name); - if (paramValues == null) { - fail("No queryParam [" + name + "]"); + List headerValues = request.getHeaders().get(name); + if (headerValues == null) { + fail("Expected header <" + name + "> to exist but was null"); } - assertThat("Request queryParam values for [" + name + "]", paramValues, matcher); + assertThat("Request header [" + name + "] values", headerValues, matcher); }; } - - private static MultiValueMap getQueryParams(ClientHttpRequest request) { - return UriComponentsBuilder.fromUri(request.getURI()).build().getQueryParams(); - } - - private static void assertValueCount( - String valueType, String name, MultiValueMap map, int count) { - - List values = map.get(name); - String message = "Expected " + valueType + " <" + name + ">"; - if (values == null) { - fail(message + " to exist but was null"); - } - if (count > values.size()) { - fail(message + " to have at least <" + count + "> values but found " + values); - } - } - /** * Assert request header values with the given Hamcrest matcher(s). - *

Note that if the header's value list is larger than the number of provided - * {@code matchers}, extra values are considered acceptable. - * See {@link #header(String, Matcher)} for a variant that takes a {@code Matcher} - * over the whole list of values. + *

If the header value list is larger than the number of provided + * {@code matchers}, no matchers will be applied to the extra header values, + * effectively ignoring the additional header values. If the number of + * provided {@code matchers} exceeds the number of header values, an + * {@link AssertionError} will be thrown to signal the mismatch. + *

See {@link #header(String, Matcher)} for a variant which accepts a + * Hamcrest {@code Matcher} that applies to the entire list of values as + * opposed to applying only to individual values. + * @param name the name of the header whose value(s) will be asserted + * @param matchers the Hamcrest matchers to apply to individual header values; + * the nth matcher is applied to the nth header value * @see #header(String, Matcher) + * @see #header(String, String...) */ @SafeVarargs public static RequestMatcher header(String name, Matcher... matchers) { @@ -212,11 +255,19 @@ public static RequestMatcher header(String name, Matcher... matc /** * Assert request header values. - *

Note that if the header's value list is larger than {@code expectedValues}, - * extra values are considered acceptable. - * See {@link #header(String, Matcher)} for a variant that takes a {@code Matcher} - * over the whole list of values. + *

If the header value list is larger than the number of {@code expectedValues}, + * no matchers will be applied to the extra header values, effectively ignoring the + * additional header values. If the number of {@code expectedValues} exceeds the + * number of header values, an {@link AssertionError} will be thrown to signal the + * mismatch. + *

See {@link #header(String, Matcher)} for a variant which accepts a + * Hamcrest {@code Matcher} that applies to the entire list of values as + * opposed to applying only to individual values. + * @param name the name of the header whose value(s) will be asserted + * @param expectedValues the expected values of individual header values; the + * nth expected value is compared to the nth header value * @see #header(String, Matcher) + * @see #header(String, Matcher...) */ public static RequestMatcher header(String name, String... expectedValues) { return request -> { @@ -229,27 +280,6 @@ public static RequestMatcher header(String name, String... expectedValues) { }; } - /** - * Assert request header, matching on the whole {@code List} of values. - *

This can be used to check that the list has at least one value matching a - * criteria ({@link Matchers#hasItem(Matcher)}), or that every value in the list - * matches a common criteria ({@link Matchers#everyItem(Matcher)}), or that each - * value in the list matches its corresponding dedicated criteria - * ({@link Matchers#contains(Matcher[])}, and more. - * @param name the name of the request header to consider - * @param matcher the matcher to apply to the whole list of values for that header - * @since 5.3.26 - */ - public static RequestMatcher header(String name, Matcher> matcher) { - return request -> { - List headerValues = request.getHeaders().get(name); - if (headerValues == null) { - fail("No header values for header [" + name + "]"); - } - assertThat("Request header values for [" + name + "]", headerValues, matcher); - }; - } - /** * Assert that the given request header does not exist. * @since 5.2 @@ -323,4 +353,18 @@ public static XpathRequestMatchers xpath(String expression, Map return new XpathRequestMatchers(expression, namespaces, args); } + + private static void assertValueCount( + String valueType, String name, MultiValueMap map, int count) { + + List values = map.get(name); + String message = "Expected " + valueType + " <" + name + ">"; + if (values == null) { + fail(message + " to exist but was null"); + } + if (count > values.size()) { + fail(message + " to have at least <" + count + "> values but found " + values); + } + } + } diff --git a/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java index a6e156514920..6b575533c18f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java @@ -18,25 +18,23 @@ import java.io.IOException; import java.net.URI; -import java.util.Arrays; -import java.util.Collections; import java.util.List; -import org.hamcrest.CoreMatchers; +import org.assertj.core.api.AssertionsForClassTypes; +import org.assertj.core.api.ThrowableTypeAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; import org.springframework.mock.http.client.MockClientHttpRequest; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.any; import static org.hamcrest.Matchers.anything; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.either; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.hasItem; @@ -52,6 +50,7 @@ * @author Craig Walls * @author Rossen Stoyanchev * @author Sam Brannen + * @author Simon Baslé */ class MockRestRequestMatchersTests { @@ -76,9 +75,8 @@ void requestToUriTemplate() throws Exception { void requestToNoMatch() { this.request.setURI(URI.create("http://www.foo.example/bar")); - assertThatThrownBy( - () -> MockRestRequestMatchers.requestTo("http://www.foo.example/wrong").match(this.request)) - .isInstanceOf(AssertionError.class); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.requestTo("http://www.foo.example/wrong").match(this.request)); } @Test @@ -99,14 +97,14 @@ void method() throws Exception { void methodNoMatch() { this.request.setMethod(HttpMethod.POST); - assertThatThrownBy(() -> MockRestRequestMatchers.method(HttpMethod.GET).match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("expected: but was:"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.method(HttpMethod.GET).match(this.request)) + .withMessageContaining("expected: but was:"); } @Test void header() throws Exception { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); + this.request.getHeaders().put("foo", List.of("bar", "baz")); MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request); } @@ -117,62 +115,62 @@ void headerDoesNotExist() throws Exception { MockRestRequestMatchers.headerDoesNotExist("").match(this.request); MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request); - List values = Arrays.asList("bar", "baz"); + List values = List.of("bar", "baz"); this.request.getHeaders().put("foo", values); - assertThatThrownBy(() -> MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessage("Expected header not to exist, but it exists with values: " + values); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request)) + .withMessage("Expected header not to exist, but it exists with values: " + values); } @Test void headerMissing() { - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("was null"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request)) + .withMessageContaining("was null"); } @Test void headerMissingValue() { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); + this.request.getHeaders().put("foo", List.of("bar", "baz")); - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", "bad").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("expected: but was:"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bad").match(this.request)) + .withMessageContaining("expected: but was:"); } @Test void headerContains() throws Exception { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); + this.request.getHeaders().put("foo", List.of("bar", "baz")); MockRestRequestMatchers.header("foo", containsString("ba")).match(this.request); } @Test void headerContainsWithMissingHeader() { - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("baz")).match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("but was null"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("baz")).match(this.request)) + .withMessageContaining("but was null"); } @Test void headerContainsWithMissingValue() { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); + this.request.getHeaders().put("foo", List.of("bar", "baz")); - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("bx")).match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("was \"bar\""); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("bx")).match(this.request)) + .withMessageContaining("was \"bar\""); } @Test void headerListMissing() { - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", hasSize(2)).match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessage("No header values for header [foo]"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", hasSize(2)).match(this.request)) + .withMessage("Expected header to exist but was null"); } @Test void headerListMatchers() throws IOException { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); + this.request.getHeaders().put("foo", List.of("bar", "baz")); MockRestRequestMatchers.header("foo", containsInAnyOrder(endsWith("baz"), endsWith("bar"))).match(this.request); MockRestRequestMatchers.header("foo", contains(is("bar"), is("baz"))).match(this.request); @@ -181,66 +179,71 @@ void headerListMatchers() throws IOException { MockRestRequestMatchers.header("foo", everyItem(startsWith("ba"))).match(this.request); MockRestRequestMatchers.header("foo", hasSize(2)).match(this.request); - //these can be a bit ambiguous when reading the test (the compiler selects the list matcher): + // These can be a bit ambiguous when reading the test (the compiler selects the list matcher): MockRestRequestMatchers.header("foo", notNullValue()).match(this.request); MockRestRequestMatchers.header("foo", is(anything())).match(this.request); MockRestRequestMatchers.header("foo", allOf(notNullValue(), notNullValue())).match(this.request); - //these are not as ambiguous thanks to an inner matcher that is either obviously list-oriented, - //string-oriented or obviously a vararg of matchers - //list matcher version + // These are not as ambiguous thanks to an inner matcher that is either obviously list-oriented, + // string-oriented, or obviously a vararg of matchers + + // list matcher version MockRestRequestMatchers.header("foo", allOf(notNullValue(), hasSize(2))).match(this.request); - //vararg version + + // vararg version MockRestRequestMatchers.header("foo", allOf(notNullValue(), endsWith("ar"))).match(this.request); MockRestRequestMatchers.header("foo", is((any(String.class)))).match(this.request); - MockRestRequestMatchers.header("foo", CoreMatchers.either(is("bar")).or(is(nullValue()))).match(this.request); + MockRestRequestMatchers.header("foo", either(is("bar")).or(is(nullValue()))).match(this.request); MockRestRequestMatchers.header("foo", is(notNullValue()), is(notNullValue())).match(this.request); } @Test void headerListContainsMismatch() { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); - - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers - .header("foo", contains(containsString("ba"))).match(this.request)) - .withMessage("Request header values for [foo]" + System.lineSeparator() - + "Expected: iterable containing [a string containing \"ba\"]" + System.lineSeparator() - + " but: not matched: \"baz\""); - - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers - .header("foo", hasItem(endsWith("ba"))).match(this.request)) - .withMessage("Request header values for [foo]" + System.lineSeparator() - + "Expected: a collection containing a string ending with \"ba\"" + System.lineSeparator() - + " but: mismatches were: [was \"bar\", was \"baz\"]"); - - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers - .header("foo", everyItem(endsWith("ar"))).match(this.request)) - .withMessage("Request header values for [foo]" + System.lineSeparator() - + "Expected: every item is a string ending with \"ar\"" + System.lineSeparator() - + " but: an item was \"baz\""); + this.request.getHeaders().put("foo", List.of("bar", "baz")); + + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", contains(containsString("ba"))).match(this.request)) + .withMessageContainingAll( + "Request header [foo] values", + "Expected: iterable containing [a string containing \"ba\"]", + "but: not matched: \"baz\""); + + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", hasItem(endsWith("ba"))).match(this.request)) + .withMessageContainingAll( + "Request header [foo] values", + "Expected: a collection containing a string ending with \"ba\"", + "but: mismatches were: [was \"bar\", was \"baz\"]"); + + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", everyItem(endsWith("ar"))).match(this.request)) + .withMessageContainingAll( + "Request header [foo] values", + "Expected: every item is a string ending with \"ar\"", + "but: an item was \"baz\""); } @Test void headers() throws Exception { - this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); + this.request.getHeaders().put("foo", List.of("bar", "baz")); MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request); } @Test void headersWithMissingHeader() { - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("but was null"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request)) + .withMessageContaining("but was null"); } @Test void headersWithMissingValue() { - this.request.getHeaders().put("foo", Collections.singletonList("bar")); + this.request.getHeaders().put("foo", List.of("bar")); - assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("to have at least <2> values"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request)) + .withMessageContaining("to have at least <2> values"); } @Test @@ -254,18 +257,18 @@ void queryParam() throws Exception { void queryParamMissing() { this.request.setURI(URI.create("http://www.foo.example/a")); - assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bar").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("but was null"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bar").match(this.request)) + .withMessageContaining("but was null"); } @Test void queryParamMissingValue() { this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz")); - assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bad").match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("expected: but was:"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bad").match(this.request)) + .withMessageContaining("expected: but was:"); } @Test @@ -279,17 +282,17 @@ void queryParamContains() throws Exception { void queryParamContainsWithMissingValue() { this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz")); - assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", containsString("bx")).match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessageContaining("was \"bar\""); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", containsString("bx")).match(this.request)) + .withMessageContaining("was \"bar\""); } @Test void queryParamListMissing() { - assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", hasSize(2)).match(this.request)) - .isInstanceOf(AssertionError.class) - .hasMessage("No queryParam [foo]"); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", hasSize(2)).match(this.request)) + .withMessage("Expected query param to exist but was null"); } @Test @@ -303,19 +306,21 @@ void queryParamListMatchers() throws IOException { MockRestRequestMatchers.queryParam("foo", everyItem(startsWith("ba"))).match(this.request); MockRestRequestMatchers.queryParam("foo", hasSize(2)).match(this.request); - //these can be a bit ambiguous when reading the test (the compiler selects the list matcher): + // These can be a bit ambiguous when reading the test (the compiler selects the list matcher): MockRestRequestMatchers.queryParam("foo", notNullValue()).match(this.request); MockRestRequestMatchers.queryParam("foo", is(anything())).match(this.request); MockRestRequestMatchers.queryParam("foo", allOf(notNullValue(), notNullValue())).match(this.request); - //these are not as ambiguous thanks to an inner matcher that is either obviously list-oriented, - //string-oriented or obviously a vararg of matchers - //list matcher version + // These are not as ambiguous thanks to an inner matcher that is either obviously list-oriented, + // string-oriented, or obviously a vararg of matchers + + // list matcher version MockRestRequestMatchers.queryParam("foo", allOf(notNullValue(), hasSize(2))).match(this.request); - //vararg version + + // vararg version MockRestRequestMatchers.queryParam("foo", allOf(notNullValue(), endsWith("ar"))).match(this.request); MockRestRequestMatchers.queryParam("foo", is((any(String.class)))).match(this.request); - MockRestRequestMatchers.queryParam("foo", CoreMatchers.either(is("bar")).or(is(nullValue()))).match(this.request); + MockRestRequestMatchers.queryParam("foo", either(is("bar")).or(is(nullValue()))).match(this.request); MockRestRequestMatchers.queryParam("foo", is(notNullValue()), is(notNullValue())).match(this.request); } @@ -323,23 +328,30 @@ void queryParamListMatchers() throws IOException { void queryParamListContainsMismatch() { this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz")); - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers - .queryParam("foo", contains(containsString("ba"))).match(this.request)) - .withMessage("Request queryParam values for [foo]" + System.lineSeparator() - + "Expected: iterable containing [a string containing \"ba\"]" + System.lineSeparator() - + " but: not matched: \"baz\""); - - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers - .queryParam("foo", hasItem(endsWith("ba"))).match(this.request)) - .withMessage("Request queryParam values for [foo]" + System.lineSeparator() - + "Expected: a collection containing a string ending with \"ba\"" + System.lineSeparator() - + " but: mismatches were: [was \"bar\", was \"baz\"]"); - - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers - .queryParam("foo", everyItem(endsWith("ar"))).match(this.request)) - .withMessage("Request queryParam values for [foo]" + System.lineSeparator() - + "Expected: every item is a string ending with \"ar\"" + System.lineSeparator() - + " but: an item was \"baz\""); + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", contains(containsString("ba"))).match(this.request)) + .withMessageContainingAll( + "Query param [foo] values", + "Expected: iterable containing [a string containing \"ba\"]", + "but: not matched: \"baz\""); + + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", hasItem(endsWith("ba"))).match(this.request)) + .withMessageContainingAll( + "Query param [foo] values", + "Expected: a collection containing a string ending with \"ba\"", + "but: mismatches were: [was \"bar\", was \"baz\"]"); + + assertThatAssertionError() + .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", everyItem(endsWith("ar"))).match(this.request)) + .withMessageContainingAll( + "Query param [foo] values", + "Expected: every item is a string ending with \"ar\"", + "but: an item was \"baz\""); + } + + private static ThrowableTypeAssert assertThatAssertionError() { + return AssertionsForClassTypes.assertThatExceptionOfType(AssertionError.class); } }