Browse Source

Add Consumer methods to WebTestClient assertion classes

Issue: SPR-16574
pull/1651/merge
Rossen Stoyanchev 8 years ago
parent
commit
91122ec0f5
  1. 69
      spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java
  2. 166
      spring-test/src/main/java/org/springframework/test/util/XpathExpectationsHelper.java
  3. 6
      spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java
  4. 13
      spring-test/src/main/java/org/springframework/test/web/reactive/server/HeaderAssertions.java
  5. 24
      spring-test/src/main/java/org/springframework/test/web/reactive/server/JsonPathAssertions.java
  6. 13
      spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java
  7. 6
      spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java
  8. 37
      spring-test/src/main/java/org/springframework/test/web/reactive/server/XpathAssertions.java
  9. 13
      spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java

69
spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java

@ -20,19 +20,15 @@ import java.util.List; @@ -20,19 +20,15 @@ import java.util.List;
import java.util.Map;
import com.jayway.jsonpath.JsonPath;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.springframework.test.util.AssertionErrors.assertEquals;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.springframework.test.util.AssertionErrors.fail;
/**
* A helper class for applying assertions via JSON path expressions.
*
@ -74,7 +70,7 @@ public class JsonPathExpectationsHelper { @@ -74,7 +70,7 @@ public class JsonPathExpectationsHelper {
@SuppressWarnings("unchecked")
public <T> void assertValue(String content, Matcher<T> matcher) {
T value = (T) evaluateJsonPath(content);
assertThat("JSON path \"" + this.expression + "\"", value, matcher);
MatcherAssert.assertThat("JSON path \"" + this.expression + "\"", value, matcher);
}
/**
@ -89,7 +85,7 @@ public class JsonPathExpectationsHelper { @@ -89,7 +85,7 @@ public class JsonPathExpectationsHelper {
@SuppressWarnings("unchecked")
public <T> void assertValue(String content, Matcher<T> matcher, Class<T> targetType) {
T value = (T) evaluateJsonPath(content, targetType);
assertThat("JSON path \"" + this.expression + "\"", value, matcher);
MatcherAssert.assertThat("JSON path \"" + this.expression + "\"", value, matcher);
}
/**
@ -104,10 +100,11 @@ public class JsonPathExpectationsHelper { @@ -104,10 +100,11 @@ public class JsonPathExpectationsHelper {
@SuppressWarnings("rawtypes")
List actualValueList = (List) actualValue;
if (actualValueList.isEmpty()) {
fail("No matching value at JSON path \"" + this.expression + "\"");
AssertionErrors.fail("No matching value at JSON path \"" + this.expression + "\"");
}
if (actualValueList.size() != 1) {
fail("Got a list of values " + actualValue + " instead of the expected single value " + expectedValue);
AssertionErrors.fail("Got a list of values " + actualValue +
" instead of the expected single value " + expectedValue);
}
actualValue = actualValueList.get(0);
}
@ -116,7 +113,7 @@ public class JsonPathExpectationsHelper { @@ -116,7 +113,7 @@ public class JsonPathExpectationsHelper {
actualValue = evaluateJsonPath(content, expectedValue.getClass());
}
}
assertEquals("JSON path \"" + this.expression + "\"", expectedValue, actualValue);
AssertionErrors.assertEquals("JSON path \"" + this.expression + "\"", expectedValue, actualValue);
}
/**
@ -127,7 +124,7 @@ public class JsonPathExpectationsHelper { @@ -127,7 +124,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsString(String content) {
Object value = assertExistsAndReturn(content);
assertThat(failureReason("a string", value), value, instanceOf(String.class));
MatcherAssert.assertThat(failureReason("a string", value), value, CoreMatchers.instanceOf(String.class));
}
/**
@ -138,7 +135,7 @@ public class JsonPathExpectationsHelper { @@ -138,7 +135,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsBoolean(String content) {
Object value = assertExistsAndReturn(content);
assertThat(failureReason("a boolean", value), value, instanceOf(Boolean.class));
MatcherAssert.assertThat(failureReason("a boolean", value), value, CoreMatchers.instanceOf(Boolean.class));
}
/**
@ -149,7 +146,7 @@ public class JsonPathExpectationsHelper { @@ -149,7 +146,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsNumber(String content) {
Object value = assertExistsAndReturn(content);
assertThat(failureReason("a number", value), value, instanceOf(Number.class));
MatcherAssert.assertThat(failureReason("a number", value), value, CoreMatchers.instanceOf(Number.class));
}
/**
@ -159,7 +156,7 @@ public class JsonPathExpectationsHelper { @@ -159,7 +156,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsArray(String content) {
Object value = assertExistsAndReturn(content);
assertThat(failureReason("an array", value), value, instanceOf(List.class));
MatcherAssert.assertThat(failureReason("an array", value), value, CoreMatchers.instanceOf(List.class));
}
/**
@ -170,7 +167,7 @@ public class JsonPathExpectationsHelper { @@ -170,7 +167,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsMap(String content) {
Object value = assertExistsAndReturn(content);
assertThat(failureReason("a map", value), value, instanceOf(Map.class));
MatcherAssert.assertThat(failureReason("a map", value), value, CoreMatchers.instanceOf(Map.class));
}
/**
@ -204,10 +201,10 @@ public class JsonPathExpectationsHelper { @@ -204,10 +201,10 @@ public class JsonPathExpectationsHelper {
}
String reason = failureReason("no value", value);
if (pathIsIndefinite() && value instanceof List) {
assertTrue(reason, ((List<?>) value).isEmpty());
AssertionErrors.assertTrue(reason, ((List<?>) value).isEmpty());
}
else {
assertTrue(reason, (value == null));
AssertionErrors.assertTrue(reason, (value == null));
}
}
@ -220,7 +217,7 @@ public class JsonPathExpectationsHelper { @@ -220,7 +217,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsEmpty(String content) {
Object value = evaluateJsonPath(content);
assertTrue(failureReason("an empty value", value), ObjectUtils.isEmpty(value));
AssertionErrors.assertTrue(failureReason("an empty value", value), ObjectUtils.isEmpty(value));
}
/**
@ -232,7 +229,7 @@ public class JsonPathExpectationsHelper { @@ -232,7 +229,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsNotEmpty(String content) {
Object value = evaluateJsonPath(content);
assertTrue(failureReason("a non-empty value", value), !ObjectUtils.isEmpty(value));
AssertionErrors.assertTrue(failureReason("a non-empty value", value), !ObjectUtils.isEmpty(value));
}
/**
@ -247,7 +244,8 @@ public class JsonPathExpectationsHelper { @@ -247,7 +244,8 @@ public class JsonPathExpectationsHelper {
public void hasJsonPath(String content) {
Object value = evaluateJsonPath(content);
if (pathIsIndefinite() && value instanceof List) {
assertTrue("No values for JSON path \"" + this.expression + "\"", !((List<?>) value).isEmpty());
String message = "No values for JSON path \"" + this.expression + "\"";
AssertionErrors.assertTrue(message, !((List<?>) value).isEmpty());
}
}
@ -270,10 +268,10 @@ public class JsonPathExpectationsHelper { @@ -270,10 +268,10 @@ public class JsonPathExpectationsHelper {
return;
}
if (pathIsIndefinite() && value instanceof List) {
assertTrue(failureReason("no values", value), ((List<?>) value).isEmpty());
AssertionErrors.assertTrue(failureReason("no values", value), ((List<?>) value).isEmpty());
}
else {
fail(failureReason("no value", value));
AssertionErrors.fail(failureReason("no value", value));
}
}
@ -282,18 +280,31 @@ public class JsonPathExpectationsHelper { @@ -282,18 +280,31 @@ public class JsonPathExpectationsHelper {
ObjectUtils.nullSafeToString(StringUtils.quoteIfString(value)));
}
/**
* Evaluate the JSON path and return the resulting value.
* @param content the content to evaluate against
* @return the result of the evaluation
* @throws AssertionError if the evaluation fails
*/
@Nullable
private Object evaluateJsonPath(String content) {
public Object evaluateJsonPath(String content) {
try {
return this.jsonPath.read(content);
}
catch (Throwable ex) {
String message = "No value at JSON path \"" + this.expression + "\"";
throw new AssertionError(message, ex);
throw new AssertionError("No value at JSON path \"" + this.expression + "\"", ex);
}
}
private Object evaluateJsonPath(String content, Class<?> targetType) {
/**
* Variant of {@link #evaluateJsonPath(String)} with a target type.
* This can be useful for matching numbers reliably for example coercing an
* integer into a double.
* @param content the content to evaluate against
* @return the result of the evaluation
* @throws AssertionError if the evaluation fails
*/
public Object evaluateJsonPath(String content, Class<?> targetType) {
try {
return JsonPath.parse(content).read(this.expression, targetType);
}
@ -307,9 +318,9 @@ public class JsonPathExpectationsHelper { @@ -307,9 +318,9 @@ public class JsonPathExpectationsHelper {
private Object assertExistsAndReturn(String content) {
Object value = evaluateJsonPath(content);
String reason = "No value at JSON path \"" + this.expression + "\"";
assertTrue(reason, value != null);
AssertionErrors.assertTrue(reason, value != null);
if (pathIsIndefinite() && value instanceof List) {
assertTrue(reason, !((List<?>) value).isEmpty());
AssertionErrors.assertTrue(reason, !((List<?>) value).isEmpty());
}
return value;
}

166
spring-test/src/main/java/org/springframework/test/util/XpathExpectationsHelper.java

@ -29,6 +29,7 @@ import javax.xml.xpath.XPathExpressionException; @@ -29,6 +29,7 @@ import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@ -39,9 +40,6 @@ import org.springframework.util.CollectionUtils; @@ -39,9 +40,6 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.SimpleNamespaceContext;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.springframework.test.util.AssertionErrors.assertEquals;
import static org.springframework.test.util.AssertionErrors.assertTrue;
/**
* A helper class for applying assertions via XPath expressions.
@ -74,9 +72,8 @@ public class XpathExpectationsHelper { @@ -74,9 +72,8 @@ public class XpathExpectationsHelper {
this.hasNamespaces = !CollectionUtils.isEmpty(namespaces);
}
private XPathExpression compileXpathExpression(String expression, @Nullable Map<String, String> namespaces)
throws XPathExpressionException {
private static XPathExpression compileXpathExpression(String expression,
@Nullable Map<String, String> namespaces) throws XPathExpressionException {
SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
namespaceContext.setBindings(namespaces != null ? namespaces : Collections.emptyMap());
@ -85,6 +82,7 @@ public class XpathExpectationsHelper { @@ -85,6 +82,7 @@ public class XpathExpectationsHelper {
return xpath.compile(expression);
}
/**
* Return the compiled XPath expression.
*/
@ -92,6 +90,7 @@ public class XpathExpectationsHelper { @@ -92,6 +90,7 @@ public class XpathExpectationsHelper {
return this.xpathExpression;
}
/**
* Parse the content, evaluate the XPath expression as a {@link Node},
* and assert it with the given {@code Matcher<Node>}.
@ -99,38 +98,8 @@ public class XpathExpectationsHelper { @@ -99,38 +98,8 @@ public class XpathExpectationsHelper {
public void assertNode(byte[] content, @Nullable String encoding, final Matcher<? super Node> matcher)
throws Exception {
Document document = parseXmlByteArray(content, encoding);
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
assertThat("XPath " + this.expression, node, matcher);
}
/**
* Parse the given XML content to a {@link Document}.
* @param xml the content to parse
* @param encoding optional content encoding, if provided as metadata (e.g. in HTTP headers)
* @return the parsed document
*/
protected Document parseXmlByteArray(byte[] xml, @Nullable String encoding) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(this.hasNamespaces);
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new ByteArrayInputStream(xml));
if (StringUtils.hasText(encoding)) {
inputSource.setEncoding(encoding);
}
return documentBuilder.parse(inputSource);
}
/**
* Apply the XPath expression to given document.
* @throws XPathExpressionException if expression evaluation failed
*/
@SuppressWarnings("unchecked")
@Nullable
protected <T> T evaluateXpath(Document document, QName evaluationType, Class<T> expectedClass)
throws XPathExpressionException {
return (T) getXpathExpression().evaluate(document, evaluationType);
Node node = evaluateXpath(content, encoding, Node.class);
MatcherAssert.assertThat("XPath " + this.expression, node, matcher);
}
/**
@ -138,9 +107,8 @@ public class XpathExpectationsHelper { @@ -138,9 +107,8 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void exists(byte[] content, @Nullable String encoding) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
assertTrue("XPath " + this.expression + " does not exist", node != null);
Node node = evaluateXpath(content, encoding, Node.class);
AssertionErrors.assertTrue("XPath " + this.expression + " does not exist", node != null);
}
/**
@ -148,9 +116,8 @@ public class XpathExpectationsHelper { @@ -148,9 +116,8 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void doesNotExist(byte[] content, @Nullable String encoding) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
assertTrue("XPath " + this.expression + " exists", node == null);
Node node = evaluateXpath(content, encoding, Node.class);
AssertionErrors.assertTrue("XPath " + this.expression + " exists", node == null);
}
/**
@ -158,11 +125,12 @@ public class XpathExpectationsHelper { @@ -158,11 +125,12 @@ public class XpathExpectationsHelper {
* given Hamcrest matcher.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNodeCount(byte[] content, @Nullable String encoding, Matcher<Integer> matcher) throws Exception {
Document document = parseXmlByteArray(content, encoding);
NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
assertThat("nodeCount for XPath " + this.expression,
(nodeList != null ? nodeList.getLength() : 0), matcher);
public void assertNodeCount(byte[] content, @Nullable String encoding, Matcher<Integer> matcher)
throws Exception {
NodeList nodeList = evaluateXpath(content, encoding, NodeList.class);
String reason = "nodeCount for XPath " + this.expression;
MatcherAssert.assertThat(reason, nodeList != null ? nodeList.getLength() : 0, matcher);
}
/**
@ -170,9 +138,8 @@ public class XpathExpectationsHelper { @@ -170,9 +138,8 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNodeCount(byte[] content, @Nullable String encoding, int expectedCount) throws Exception {
Document document = parseXmlByteArray(content, encoding);
NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
assertEquals("nodeCount for XPath " + this.expression, expectedCount,
NodeList nodeList = evaluateXpath(content, encoding, NodeList.class);
AssertionErrors.assertEquals("nodeCount for XPath " + this.expression, expectedCount,
(nodeList != null ? nodeList.getLength() : 0));
}
@ -181,10 +148,11 @@ public class XpathExpectationsHelper { @@ -181,10 +148,11 @@ public class XpathExpectationsHelper {
* given Hamcrest matcher.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertString(byte[] content, @Nullable String encoding, Matcher<? super String> matcher) throws Exception {
Document document = parseXmlByteArray(content, encoding);
String result = evaluateXpath(document, XPathConstants.STRING, String.class);
assertThat("XPath " + this.expression, result, matcher);
public void assertString(byte[] content, @Nullable String encoding, Matcher<? super String> matcher)
throws Exception {
String actual = evaluateXpath(content, encoding, String.class);
MatcherAssert.assertThat("XPath " + this.expression, actual, matcher);
}
/**
@ -192,9 +160,8 @@ public class XpathExpectationsHelper { @@ -192,9 +160,8 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertString(byte[] content, @Nullable String encoding, String expectedValue) throws Exception {
Document document = parseXmlByteArray(content, encoding);
String actual = evaluateXpath(document, XPathConstants.STRING, String.class);
assertEquals("XPath " + this.expression, expectedValue, actual);
String actual = evaluateXpath(content, encoding, String.class);
AssertionErrors.assertEquals("XPath " + this.expression, expectedValue, actual);
}
/**
@ -203,9 +170,8 @@ public class XpathExpectationsHelper { @@ -203,9 +170,8 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNumber(byte[] content, @Nullable String encoding, Matcher<? super Double> matcher) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Double result = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
assertThat("XPath " + this.expression, result, matcher);
Double actual = evaluateXpath(content, encoding, Double.class);
MatcherAssert.assertThat("XPath " + this.expression, actual, matcher);
}
/**
@ -213,9 +179,8 @@ public class XpathExpectationsHelper { @@ -213,9 +179,8 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNumber(byte[] content, @Nullable String encoding, Double expectedValue) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Double actual = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
assertEquals("XPath " + this.expression, expectedValue, actual);
Double actual = evaluateXpath(content, encoding, Double.class);
AssertionErrors.assertEquals("XPath " + this.expression, expectedValue, actual);
}
/**
@ -223,9 +188,76 @@ public class XpathExpectationsHelper { @@ -223,9 +188,76 @@ public class XpathExpectationsHelper {
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertBoolean(byte[] content, @Nullable String encoding, boolean expectedValue) throws Exception {
String actual = evaluateXpath(content, encoding, String.class);
AssertionErrors.assertEquals("XPath " + this.expression, expectedValue, Boolean.parseBoolean(actual));
}
/**
* Evaluate the XPath and return the resulting value.
* @param content the content to evaluate against
* @param encoding the encoding to use (optionally)
* @param targetClass the target class, one of Number, String, Boolean,
* org.w3c.Node, or NodeList
* @throws Exception if content parsing or expression evaluation fails
* @since 5.1
*/
@Nullable
public <T> T evaluateXpath(byte[] content, @Nullable String encoding, Class<T> targetClass) throws Exception {
Document document = parseXmlByteArray(content, encoding);
String actual = evaluateXpath(document, XPathConstants.STRING, String.class);
assertEquals("XPath " + this.expression, expectedValue, Boolean.parseBoolean(actual));
return evaluateXpath(document, toQName(targetClass), targetClass);
}
/**
* Parse the given XML content to a {@link Document}.
* @param xml the content to parse
* @param encoding optional content encoding, if provided as metadata (e.g. in HTTP headers)
* @return the parsed document
*/
protected Document parseXmlByteArray(byte[] xml, @Nullable String encoding) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(this.hasNamespaces);
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new ByteArrayInputStream(xml));
if (StringUtils.hasText(encoding)) {
inputSource.setEncoding(encoding);
}
return documentBuilder.parse(inputSource);
}
/**
* Apply the XPath expression to given document.
* @throws XPathExpressionException if expression evaluation failed
*/
@SuppressWarnings("unchecked")
@Nullable
protected <T> T evaluateXpath(Document document, QName evaluationType, Class<T> expectedClass)
throws XPathExpressionException {
return (T) getXpathExpression().evaluate(document, evaluationType);
}
private <T> QName toQName(Class<T> expectedClass) {
QName evaluationType;
if (Number.class.isAssignableFrom(expectedClass)) {
evaluationType = XPathConstants.NUMBER;
}
else if (CharSequence.class.isAssignableFrom(expectedClass)) {
evaluationType = XPathConstants.STRING;
}
else if (Boolean.class.isAssignableFrom(expectedClass)) {
evaluationType = XPathConstants.BOOLEAN;
}
else if (Node.class.isAssignableFrom(expectedClass)) {
evaluationType = XPathConstants.NODE;
}
else if (NodeList.class.isAssignableFrom(expectedClass)) {
evaluationType = XPathConstants.NODESET;
}
else {
throw new IllegalArgumentException("Unexpected target class " + expectedClass + ". " +
"Supported: numbers, strings, boolean, and org.w3c.Node and NodeList");
}
return evaluationType;
}
}

6
spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java

@ -402,6 +402,12 @@ class DefaultWebTestClient implements WebTestClient { @@ -402,6 +402,12 @@ class DefaultWebTestClient implements WebTestClient {
return self();
}
@Override
public <T extends S> T value(Consumer<B> consumer) {
this.result.assertWithDiagnostics(() -> consumer.accept(this.result.getResponseBody()));
return self();
}
@Override
public <T extends S> T consumeWith(Consumer<EntityExchangeResult<B>> consumer) {
this.result.assertWithDiagnostics(() -> consumer.accept(this.result));

13
spring-test/src/main/java/org/springframework/test/web/reactive/server/HeaderAssertions.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.test.web.reactive.server;
import java.util.Arrays;
import java.util.function.Consumer;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
@ -81,6 +82,18 @@ public class HeaderAssertions { @@ -81,6 +82,18 @@ public class HeaderAssertions {
return this.responseSpec;
}
/**
* Assert the primary value of the response header with a {@link Matcher}.
* @param name the header name
* @param consumer the matcher to sue
* @since 5.1
*/
public WebTestClient.ResponseSpec value(String name, Consumer<String> consumer) {
String value = getRequiredValue(name);
this.exchangeResult.assertWithDiagnostics(() -> consumer.accept(value));
return this.responseSpec;
}
private String getRequiredValue(String name) {
String value = getHeaders().getFirst(name);
if (value == null) {

24
spring-test/src/main/java/org/springframework/test/web/reactive/server/JsonPathAssertions.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.test.web.reactive.server;
import java.util.function.Consumer;
import org.hamcrest.Matcher;
import org.springframework.test.util.JsonPathExpectationsHelper;
@ -152,4 +154,26 @@ public class JsonPathAssertions { @@ -152,4 +154,26 @@ public class JsonPathAssertions {
return this.bodySpec;
}
/**
* Consume the result of the JSONPath evaluation.
* @since 5.1
*/
@SuppressWarnings("unchecked")
public <T> WebTestClient.BodyContentSpec value(Consumer<T> consumer) {
Object value = this.pathHelper.evaluateJsonPath(this.content);
consumer.accept((T) value);
return this.bodySpec;
}
/**
* Consume the result of the JSONPath evaluation and provide a target class.
* @since 5.1
*/
@SuppressWarnings("unchecked")
public <T> WebTestClient.BodyContentSpec value(Consumer<T> consumer, Class<T> targetType) {
Object value = this.pathHelper.evaluateJsonPath(this.content, targetType);
consumer.accept((T) value);
return this.bodySpec;
}
}

13
spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.test.web.reactive.server;
import java.util.function.Consumer;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
@ -208,6 +210,17 @@ public class StatusAssertions { @@ -208,6 +210,17 @@ public class StatusAssertions {
return this.responseSpec;
}
/**
* Match the response status value with a Hamcrest matcher.
* @param consumer the matcher to use
* @since 5.1
*/
public WebTestClient.ResponseSpec value(Consumer<Integer> consumer) {
int value = this.exchangeResult.getStatus().value();
this.exchangeResult.assertWithDiagnostics(() -> consumer.accept(value));
return this.responseSpec;
}
private WebTestClient.ResponseSpec assertStatusAndReturn(HttpStatus expected) {
HttpStatus actual = this.exchangeResult.getStatus();

6
spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java

@ -772,6 +772,12 @@ public interface WebTestClient { @@ -772,6 +772,12 @@ public interface WebTestClient {
*/
<T extends S, R> T value(Function<B, R> bodyMapper, Matcher<R> matcher);
/**
* Assert the extracted body with a {@link Matcher}.
* @since 5.1
*/
<T extends S> T value(Consumer<B> consumer);
/**
* Assert the exchange result with the given {@link Consumer}.
*/

37
spring-test/src/main/java/org/springframework/test/web/reactive/server/XpathAssertions.java

@ -19,6 +19,7 @@ package org.springframework.test.web.reactive.server; @@ -19,6 +19,7 @@ package org.springframework.test.web.reactive.server;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.Matcher;
@ -107,6 +108,7 @@ public class XpathAssertions { @@ -107,6 +108,7 @@ public class XpathAssertions {
/**
* Delegates to {@link XpathExpectationsHelper#assertString(byte[], String, Matcher)}.
* @since 5.1
*/
public WebTestClient.BodyContentSpec string(Matcher<? super String> matcher){
return assertWith(() -> this.xpathHelper.assertString(getContent(), getCharset(), matcher));
@ -114,6 +116,7 @@ public class XpathAssertions { @@ -114,6 +116,7 @@ public class XpathAssertions {
/**
* Delegates to {@link XpathExpectationsHelper#assertNumber(byte[], String, Matcher)}.
* @since 5.1
*/
public WebTestClient.BodyContentSpec number(Matcher<? super Double> matcher){
return assertWith(() -> this.xpathHelper.assertNumber(getContent(), getCharset(), matcher));
@ -121,11 +124,45 @@ public class XpathAssertions { @@ -121,11 +124,45 @@ public class XpathAssertions {
/**
* Delegates to {@link XpathExpectationsHelper#assertNodeCount(byte[], String, Matcher)}.
* @since 5.1
*/
public WebTestClient.BodyContentSpec nodeCount(Matcher<Integer> matcher){
return assertWith(() -> this.xpathHelper.assertNodeCount(getContent(), getCharset(), matcher));
}
/**
* Consume the result of the XPath evaluation as a String.
* @since 5.1
*/
public WebTestClient.BodyContentSpec string(Consumer<String> consumer){
return assertWith(() -> {
String value = this.xpathHelper.evaluateXpath(getContent(), getCharset(), String.class);
consumer.accept(value);
});
}
/**
* Consume the result of the XPath evaluation as a Double.
* @since 5.1
*/
public WebTestClient.BodyContentSpec number(Consumer<Double> consumer){
return assertWith(() -> {
Double value = this.xpathHelper.evaluateXpath(getContent(), getCharset(), Double.class);
consumer.accept(value);
});
}
/**
* Consume the count of nodes as result of the XPath evaluation.
* @since 5.1
*/
public WebTestClient.BodyContentSpec nodeCount(Consumer<Integer> consumer){
return assertWith(() -> {
Integer value = this.xpathHelper.evaluateXpath(getContent(), getCharset(), Integer.class);
consumer.accept(value);
});
}
private WebTestClient.BodyContentSpec assertWith(CheckedExceptionTask task) {
try {

13
spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java

@ -22,6 +22,7 @@ import java.util.LinkedHashMap; @@ -22,6 +22,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.hamcrest.MatcherAssert;
import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
@ -98,6 +99,18 @@ public class ResponseEntityTests { @@ -98,6 +99,18 @@ public class ResponseEntityTests {
.expectBodyList(Person.class).isEqualTo(expected);
}
@Test
public void entityListWithConsumer() {
this.client.get()
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
.expectBodyList(Person.class).value(people -> {
MatcherAssert.assertThat(people, hasItem(new Person("Jason")));
});
}
@Test
public void entityMap() {

Loading…
Cancel
Save