Browse Source

Revise queryParam() and header() support in MockRestRequestMatchers

See gh-29953
See gh-29964
pull/29998/head
Sam Brannen 3 years ago
parent
commit
8a44b6445d
  1. 184
      spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java
  2. 218
      spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java

184
spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java

@ -23,7 +23,6 @@ import java.util.Map;
import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.Matcher; import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequest;
@ -48,6 +47,7 @@ import static org.springframework.test.util.AssertionErrors.fail;
* @author Craig Walls * @author Craig Walls
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Sam Brannen * @author Sam Brannen
* @author Simon Baslé
* @since 3.2 * @since 3.2
*/ */
public abstract class MockRestRequestMatchers { public abstract class MockRestRequestMatchers {
@ -113,13 +113,49 @@ public abstract class MockRestRequestMatchers {
return request -> assertEquals("Unexpected request", uri, request.getURI()); 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.
* <p>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<? super List<String>> matcher) {
return request -> {
MultiValueMap<String, String> params = getQueryParams(request);
List<String> 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). * Assert request query parameter values with the given Hamcrest matcher(s).
* <p>Note that if the queryParam value list is larger than the number of provided * <p>If the query parameter value list is larger than the number of provided
* {@code matchers}, extra values are considered acceptable. * {@code matchers}, no matchers will be applied to the extra query parameter
* See {@link #queryParam(String, Matcher)} for a variant that takes a * values, effectively ignoring the additional parameter values. If the number
* {@code Matcher} over the whole list of values. * of provided {@code matchers} exceeds the number of query parameter values,
* an {@link AssertionError} will be thrown to signal the mismatch.
* <p>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 n<sup>th</sup> matcher is applied to the n<sup>th</sup> query
* parameter value
* @see #queryParam(String, Matcher) * @see #queryParam(String, Matcher)
* @see #queryParam(String, String...)
*/ */
@SafeVarargs @SafeVarargs
public static RequestMatcher queryParam(String name, Matcher<? super String>... matchers) { public static RequestMatcher queryParam(String name, Matcher<? super String>... matchers) {
@ -134,11 +170,20 @@ public abstract class MockRestRequestMatchers {
/** /**
* Assert request query parameter values. * Assert request query parameter values.
* <p>Note that if the queryParam value list is larger than {@code expectedValues}, * <p>If the query parameter value list is larger than the number of
* extra values are considered acceptable. * {@code expectedValues}, no assertions will be applied to the extra query
* See {@link #queryParam(String, Matcher)} for a variant that takes a * parameter values, effectively ignoring the additional parameter values. If
* {@code Matcher} over the whole list of values. * the number of {@code expectedValues} exceeds the number of query parameter
* values, an {@link AssertionError} will be thrown to signal the mismatch.
* <p>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 n<sup>th</sup> expected value is compared to the n<sup>th</sup> query
* parameter value
* @see #queryParam(String, Matcher) * @see #queryParam(String, Matcher)
* @see #queryParam(String, Matcher...)
*/ */
public static RequestMatcher queryParam(String name, String... expectedValues) { public static RequestMatcher queryParam(String name, String... expectedValues) {
return request -> { return request -> {
@ -150,53 +195,51 @@ public abstract class MockRestRequestMatchers {
}; };
} }
private static MultiValueMap<String, String> getQueryParams(ClientHttpRequest request) {
return UriComponentsBuilder.fromUri(request.getURI()).build().getQueryParams();
}
/** /**
* Assert request query parameter, matching on the whole {@code List} of values. * Assert request header values with the given Hamcrest matcher, matching on
* <p>This can be used to check that the list has at least one value matching a * the entire {@link List} of values.
* criteria ({@link Matchers#hasItem(Matcher)}), or that every value in the list * <p>For example, this can be used to check that the list of header values
* matches a common criteria ({@link Matchers#everyItem(Matcher)}), or that each * has at least one value matching a given Hamcrest matcher (such as
* value in the list matches its corresponding dedicated criteria * {@link org.hamcrest.Matchers#hasItem(Matcher)}), that every value in the list
* ({@link Matchers#contains(Matcher[])}, and more. * matches common criteria (such as {@link org.hamcrest.Matchers#everyItem(Matcher)}),
* @param name the name of the query parameter to consider * that each value in the list matches corresponding dedicated criteria
* @param matcher the matcher to apply to the whole list of values for that header * (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 * @since 5.3.26
* @see #header(String, Matcher...)
* @see #header(String, String...)
*/ */
public static RequestMatcher queryParam(String name, Matcher<? super List<String>> matcher) { public static RequestMatcher header(String name, Matcher<? super List<String>> matcher) {
return request -> { return request -> {
MultiValueMap<String, String> params = getQueryParams(request); List<String> headerValues = request.getHeaders().get(name);
List<String> paramValues = params.get(name); if (headerValues == null) {
if (paramValues == null) { fail("Expected header <" + name + "> to exist but was null");
fail("No queryParam [" + name + "]");
} }
assertThat("Request queryParam values for [" + name + "]", paramValues, matcher); assertThat("Request header [" + name + "] values", headerValues, matcher);
}; };
} }
private static MultiValueMap<String, String> getQueryParams(ClientHttpRequest request) {
return UriComponentsBuilder.fromUri(request.getURI()).build().getQueryParams();
}
private static void assertValueCount(
String valueType, String name, MultiValueMap<String, String> map, int count) {
List<String> 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). * Assert request header values with the given Hamcrest matcher(s).
* <p>Note that if the header's value list is larger than the number of provided * <p>If the header value list is larger than the number of provided
* {@code matchers}, extra values are considered acceptable. * {@code matchers}, no matchers will be applied to the extra header values,
* See {@link #header(String, Matcher)} for a variant that takes a {@code Matcher} * effectively ignoring the additional header values. If the number of
* over the whole list of values. * provided {@code matchers} exceeds the number of header values, an
* {@link AssertionError} will be thrown to signal the mismatch.
* <p>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 n<sup>th</sup> matcher is applied to the n<sup>th</sup> header value
* @see #header(String, Matcher) * @see #header(String, Matcher)
* @see #header(String, String...)
*/ */
@SafeVarargs @SafeVarargs
public static RequestMatcher header(String name, Matcher<? super String>... matchers) { public static RequestMatcher header(String name, Matcher<? super String>... matchers) {
@ -212,11 +255,19 @@ public abstract class MockRestRequestMatchers {
/** /**
* Assert request header values. * Assert request header values.
* <p>Note that if the header's value list is larger than {@code expectedValues}, * <p>If the header value list is larger than the number of {@code expectedValues},
* extra values are considered acceptable. * no matchers will be applied to the extra header values, effectively ignoring the
* See {@link #header(String, Matcher)} for a variant that takes a {@code Matcher} * additional header values. If the number of {@code expectedValues} exceeds the
* over the whole list of values. * number of header values, an {@link AssertionError} will be thrown to signal the
* mismatch.
* <p>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
* n<sup>th</sup> expected value is compared to the n<sup>th</sup> header value
* @see #header(String, Matcher) * @see #header(String, Matcher)
* @see #header(String, Matcher...)
*/ */
public static RequestMatcher header(String name, String... expectedValues) { public static RequestMatcher header(String name, String... expectedValues) {
return request -> { return request -> {
@ -229,27 +280,6 @@ public abstract class MockRestRequestMatchers {
}; };
} }
/**
* Assert request header, matching on the whole {@code List} of values.
* <p>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<? super List<String>> matcher) {
return request -> {
List<String> 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. * Assert that the given request header does not exist.
* @since 5.2 * @since 5.2
@ -323,4 +353,18 @@ public abstract class MockRestRequestMatchers {
return new XpathRequestMatchers(expression, namespaces, args); return new XpathRequestMatchers(expression, namespaces, args);
} }
private static void assertValueCount(
String valueType, String name, MultiValueMap<String, String> map, int count) {
List<String> 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);
}
}
} }

218
spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java

@ -18,25 +18,23 @@ package org.springframework.test.web.client.match;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; 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.hamcrest.Matchers;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.mock.http.client.MockClientHttpRequest; 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.allOf;
import static org.hamcrest.Matchers.any; import static org.hamcrest.Matchers.any;
import static org.hamcrest.Matchers.anything; import static org.hamcrest.Matchers.anything;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.either;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
@ -52,6 +50,7 @@ import static org.hamcrest.Matchers.startsWith;
* @author Craig Walls * @author Craig Walls
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Sam Brannen * @author Sam Brannen
* @author Simon Baslé
*/ */
class MockRestRequestMatchersTests { class MockRestRequestMatchersTests {
@ -76,9 +75,8 @@ class MockRestRequestMatchersTests {
void requestToNoMatch() { void requestToNoMatch() {
this.request.setURI(URI.create("http://www.foo.example/bar")); this.request.setURI(URI.create("http://www.foo.example/bar"));
assertThatThrownBy( assertThatAssertionError()
() -> MockRestRequestMatchers.requestTo("http://www.foo.example/wrong").match(this.request)) .isThrownBy(() -> MockRestRequestMatchers.requestTo("http://www.foo.example/wrong").match(this.request));
.isInstanceOf(AssertionError.class);
} }
@Test @Test
@ -99,14 +97,14 @@ class MockRestRequestMatchersTests {
void methodNoMatch() { void methodNoMatch() {
this.request.setMethod(HttpMethod.POST); this.request.setMethod(HttpMethod.POST);
assertThatThrownBy(() -> MockRestRequestMatchers.method(HttpMethod.GET).match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.method(HttpMethod.GET).match(this.request))
.hasMessageContaining("expected:<GET> but was:<POST>"); .withMessageContaining("expected:<GET> but was:<POST>");
} }
@Test @Test
void header() throws Exception { 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); MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request);
} }
@ -117,62 +115,62 @@ class MockRestRequestMatchersTests {
MockRestRequestMatchers.headerDoesNotExist("").match(this.request); MockRestRequestMatchers.headerDoesNotExist("").match(this.request);
MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request); MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request);
List<String> values = Arrays.asList("bar", "baz"); List<String> values = List.of("bar", "baz");
this.request.getHeaders().put("foo", values); this.request.getHeaders().put("foo", values);
assertThatThrownBy(() -> MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.headerDoesNotExist("foo").match(this.request))
.hasMessage("Expected header <foo> not to exist, but it exists with values: " + values); .withMessage("Expected header <foo> not to exist, but it exists with values: " + values);
} }
@Test @Test
void headerMissing() { void headerMissing() {
assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request))
.hasMessageContaining("was null"); .withMessageContaining("was null");
} }
@Test @Test
void headerMissingValue() { 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)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bad").match(this.request))
.hasMessageContaining("expected:<bad> but was:<bar>"); .withMessageContaining("expected:<bad> but was:<bar>");
} }
@Test @Test
void headerContains() throws Exception { 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); MockRestRequestMatchers.header("foo", containsString("ba")).match(this.request);
} }
@Test @Test
void headerContainsWithMissingHeader() { void headerContainsWithMissingHeader() {
assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("baz")).match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("baz")).match(this.request))
.hasMessageContaining("but was null"); .withMessageContaining("but was null");
} }
@Test @Test
void headerContainsWithMissingValue() { 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)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", containsString("bx")).match(this.request))
.hasMessageContaining("was \"bar\""); .withMessageContaining("was \"bar\"");
} }
@Test @Test
void headerListMissing() { void headerListMissing() {
assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", hasSize(2)).match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", hasSize(2)).match(this.request))
.hasMessage("No header values for header [foo]"); .withMessage("Expected header <foo> to exist but was null");
} }
@Test @Test
void headerListMatchers() throws IOException { 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", containsInAnyOrder(endsWith("baz"), endsWith("bar"))).match(this.request);
MockRestRequestMatchers.header("foo", contains(is("bar"), is("baz"))).match(this.request); MockRestRequestMatchers.header("foo", contains(is("bar"), is("baz"))).match(this.request);
@ -181,66 +179,71 @@ class MockRestRequestMatchersTests {
MockRestRequestMatchers.header("foo", everyItem(startsWith("ba"))).match(this.request); MockRestRequestMatchers.header("foo", everyItem(startsWith("ba"))).match(this.request);
MockRestRequestMatchers.header("foo", hasSize(2)).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", notNullValue()).match(this.request);
MockRestRequestMatchers.header("foo", is(anything())).match(this.request); MockRestRequestMatchers.header("foo", is(anything())).match(this.request);
MockRestRequestMatchers.header("foo", allOf(notNullValue(), notNullValue())).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, // These are not as ambiguous thanks to an inner matcher that is either obviously list-oriented,
//string-oriented or obviously a vararg of matchers // string-oriented, or obviously a vararg of matchers
//list matcher version
// list matcher version
MockRestRequestMatchers.header("foo", allOf(notNullValue(), hasSize(2))).match(this.request); 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", allOf(notNullValue(), endsWith("ar"))).match(this.request);
MockRestRequestMatchers.header("foo", is((any(String.class)))).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); MockRestRequestMatchers.header("foo", is(notNullValue()), is(notNullValue())).match(this.request);
} }
@Test @Test
void headerListContainsMismatch() { void headerListContainsMismatch() {
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); this.request.getHeaders().put("foo", List.of("bar", "baz"));
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers assertThatAssertionError()
.header("foo", contains(containsString("ba"))).match(this.request)) .isThrownBy(() -> MockRestRequestMatchers.header("foo", contains(containsString("ba"))).match(this.request))
.withMessage("Request header values for [foo]" + System.lineSeparator() .withMessageContainingAll(
+ "Expected: iterable containing [a string containing \"ba\"]" + System.lineSeparator() "Request header [foo] values",
+ " but: not matched: \"baz\""); "Expected: iterable containing [a string containing \"ba\"]",
"but: not matched: \"baz\"");
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers
.header("foo", hasItem(endsWith("ba"))).match(this.request)) assertThatAssertionError()
.withMessage("Request header values for [foo]" + System.lineSeparator() .isThrownBy(() -> MockRestRequestMatchers.header("foo", hasItem(endsWith("ba"))).match(this.request))
+ "Expected: a collection containing a string ending with \"ba\"" + System.lineSeparator() .withMessageContainingAll(
+ " but: mismatches were: [was \"bar\", was \"baz\"]"); "Request header [foo] values",
"Expected: a collection containing a string ending with \"ba\"",
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers "but: mismatches were: [was \"bar\", was \"baz\"]");
.header("foo", everyItem(endsWith("ar"))).match(this.request))
.withMessage("Request header values for [foo]" + System.lineSeparator() assertThatAssertionError()
+ "Expected: every item is a string ending with \"ar\"" + System.lineSeparator() .isThrownBy(() -> MockRestRequestMatchers.header("foo", everyItem(endsWith("ar"))).match(this.request))
+ " but: an item was \"baz\""); .withMessageContainingAll(
"Request header [foo] values",
"Expected: every item is a string ending with \"ar\"",
"but: an item was \"baz\"");
} }
@Test @Test
void headers() throws Exception { 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); MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request);
} }
@Test @Test
void headersWithMissingHeader() { void headersWithMissingHeader() {
assertThatThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bar").match(this.request))
.hasMessageContaining("but was null"); .withMessageContaining("but was null");
} }
@Test @Test
void headersWithMissingValue() { 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)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request))
.hasMessageContaining("to have at least <2> values"); .withMessageContaining("to have at least <2> values");
} }
@Test @Test
@ -254,18 +257,18 @@ class MockRestRequestMatchersTests {
void queryParamMissing() { void queryParamMissing() {
this.request.setURI(URI.create("http://www.foo.example/a")); this.request.setURI(URI.create("http://www.foo.example/a"));
assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bar").match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bar").match(this.request))
.hasMessageContaining("but was null"); .withMessageContaining("but was null");
} }
@Test @Test
void queryParamMissingValue() { void queryParamMissingValue() {
this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz")); this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz"));
assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bad").match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", "bad").match(this.request))
.hasMessageContaining("expected:<bad> but was:<bar>"); .withMessageContaining("expected:<bad> but was:<bar>");
} }
@Test @Test
@ -279,17 +282,17 @@ class MockRestRequestMatchersTests {
void queryParamContainsWithMissingValue() { void queryParamContainsWithMissingValue() {
this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz")); this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz"));
assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", containsString("bx")).match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", containsString("bx")).match(this.request))
.hasMessageContaining("was \"bar\""); .withMessageContaining("was \"bar\"");
} }
@Test @Test
void queryParamListMissing() { void queryParamListMissing() {
assertThatThrownBy(() -> MockRestRequestMatchers.queryParam("foo", hasSize(2)).match(this.request)) assertThatAssertionError()
.isInstanceOf(AssertionError.class) .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", hasSize(2)).match(this.request))
.hasMessage("No queryParam [foo]"); .withMessage("Expected query param <foo> to exist but was null");
} }
@Test @Test
@ -303,19 +306,21 @@ class MockRestRequestMatchersTests {
MockRestRequestMatchers.queryParam("foo", everyItem(startsWith("ba"))).match(this.request); MockRestRequestMatchers.queryParam("foo", everyItem(startsWith("ba"))).match(this.request);
MockRestRequestMatchers.queryParam("foo", hasSize(2)).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", notNullValue()).match(this.request);
MockRestRequestMatchers.queryParam("foo", is(anything())).match(this.request); MockRestRequestMatchers.queryParam("foo", is(anything())).match(this.request);
MockRestRequestMatchers.queryParam("foo", allOf(notNullValue(), notNullValue())).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, // These are not as ambiguous thanks to an inner matcher that is either obviously list-oriented,
//string-oriented or obviously a vararg of matchers // string-oriented, or obviously a vararg of matchers
//list matcher version
// list matcher version
MockRestRequestMatchers.queryParam("foo", allOf(notNullValue(), hasSize(2))).match(this.request); 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", allOf(notNullValue(), endsWith("ar"))).match(this.request);
MockRestRequestMatchers.queryParam("foo", is((any(String.class)))).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); MockRestRequestMatchers.queryParam("foo", is(notNullValue()), is(notNullValue())).match(this.request);
} }
@ -323,23 +328,30 @@ class MockRestRequestMatchersTests {
void queryParamListContainsMismatch() { void queryParamListContainsMismatch() {
this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz")); this.request.setURI(URI.create("http://www.foo.example/a?foo=bar&foo=baz"));
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers assertThatAssertionError()
.queryParam("foo", contains(containsString("ba"))).match(this.request)) .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", contains(containsString("ba"))).match(this.request))
.withMessage("Request queryParam values for [foo]" + System.lineSeparator() .withMessageContainingAll(
+ "Expected: iterable containing [a string containing \"ba\"]" + System.lineSeparator() "Query param [foo] values",
+ " but: not matched: \"baz\""); "Expected: iterable containing [a string containing \"ba\"]",
"but: not matched: \"baz\"");
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers
.queryParam("foo", hasItem(endsWith("ba"))).match(this.request)) assertThatAssertionError()
.withMessage("Request queryParam values for [foo]" + System.lineSeparator() .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", hasItem(endsWith("ba"))).match(this.request))
+ "Expected: a collection containing a string ending with \"ba\"" + System.lineSeparator() .withMessageContainingAll(
+ " but: mismatches were: [was \"bar\", was \"baz\"]"); "Query param [foo] values",
"Expected: a collection containing a string ending with \"ba\"",
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> MockRestRequestMatchers "but: mismatches were: [was \"bar\", was \"baz\"]");
.queryParam("foo", everyItem(endsWith("ar"))).match(this.request))
.withMessage("Request queryParam values for [foo]" + System.lineSeparator() assertThatAssertionError()
+ "Expected: every item is a string ending with \"ar\"" + System.lineSeparator() .isThrownBy(() -> MockRestRequestMatchers.queryParam("foo", everyItem(endsWith("ar"))).match(this.request))
+ " but: an item was \"baz\""); .withMessageContainingAll(
"Query param [foo] values",
"Expected: every item is a string ending with \"ar\"",
"but: an item was \"baz\"");
}
private static ThrowableTypeAssert<AssertionError> assertThatAssertionError() {
return AssertionsForClassTypes.assertThatExceptionOfType(AssertionError.class);
} }
} }

Loading…
Cancel
Save