Polish
Leaving out hamcrest for now, to address more broadly. Issue: SPR-16741
This commit is contained in:
parent
2734f01067
commit
0c62d6b5da
|
|
@ -497,13 +497,8 @@ class DefaultWebTestClient implements WebTestClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XpathAssertions xpath(String expression, Map<String, String> namespaces, Object... args) {
|
public XpathAssertions xpath(String expression, @Nullable Map<String, String> namespaces, Object... args) {
|
||||||
try {
|
return new XpathAssertions(this, expression, namespaces, args);
|
||||||
return new XpathAssertions(this, expression, namespaces, args);
|
|
||||||
}
|
|
||||||
catch (XPathExpressionException ex) {
|
|
||||||
throw new AssertionError("XML parsing error", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getBodyAsString() {
|
private String getBodyAsString() {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||||
import org.springframework.http.client.reactive.ClientHttpRequest;
|
import org.springframework.http.client.reactive.ClientHttpRequest;
|
||||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.validation.Validator;
|
import org.springframework.validation.Validator;
|
||||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||||
|
|
@ -820,10 +821,15 @@ public interface WebTestClient {
|
||||||
BodyContentSpec json(String expectedJson);
|
BodyContentSpec json(String expectedJson);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the expected and actual response content as XML and perform a
|
* Parse expected and actual response content as XML and assert that
|
||||||
* comparison verifying the same structure.
|
* the two are "similar", i.e. they contain the same elements and
|
||||||
|
* attributes regardless of order.
|
||||||
|
* <p>Use of this method requires the
|
||||||
|
* <a href="https://github.com/xmlunit/xmlunit">XMLUnit</a> library on
|
||||||
|
* the classpath.
|
||||||
* @param expectedXml the expected JSON content.
|
* @param expectedXml the expected JSON content.
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
|
* @see org.springframework.test.util.XmlExpectationsHelper#assertXmlEqual(String, String)
|
||||||
*/
|
*/
|
||||||
BodyContentSpec xml(String expectedXml);
|
BodyContentSpec xml(String expectedXml);
|
||||||
|
|
||||||
|
|
@ -839,11 +845,11 @@ public interface WebTestClient {
|
||||||
JsonPathAssertions jsonPath(String expression, Object... args);
|
JsonPathAssertions jsonPath(String expression, Object... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to response body assertions using an XPath expression to inspect a specific
|
* Access to response body assertions using an XPath expression to
|
||||||
* subset of the body.
|
* inspect a specific subset of the body.
|
||||||
* <p>The XPath expression can be a parameterized string using
|
* <p>The XPath expression can be a parameterized string using
|
||||||
* formatting specifiers as defined in {@link String#format}.
|
* formatting specifiers as defined in {@link String#format}.
|
||||||
* @param expression The XPath expression
|
* @param expression the XPath expression
|
||||||
* @param args arguments to parameterize the expression
|
* @param args arguments to parameterize the expression
|
||||||
* @see #xpath(String, Map, Object...)
|
* @see #xpath(String, Map, Object...)
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
|
|
@ -853,16 +859,16 @@ public interface WebTestClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to response body assertions with specific namespaces using an XPath
|
* Access to response body assertions with specific namespaces using an
|
||||||
* expression to inspect a specific subset of the body.
|
* XPath expression to inspect a specific subset of the body.
|
||||||
* <p>The XPath expression can be a parameterized string using
|
* <p>The XPath expression can be a parameterized string using
|
||||||
* formatting specifiers as defined in {@link String#format}.
|
* formatting specifiers as defined in {@link String#format}.
|
||||||
* @param expression The XPath expression
|
* @param expression the XPath expression
|
||||||
* @param namespaces The namespaces
|
* @param namespaces namespaces to use
|
||||||
* @param args arguments to parameterize the expression
|
* @param args arguments to parameterize the expression
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
XpathAssertions xpath(String expression, Map<String, String> namespaces, Object... args);
|
XpathAssertions xpath(String expression, @Nullable Map<String, String> namespaces, Object... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert the response body content with the given {@link Consumer}.
|
* Assert the response body content with the given {@link Consumer}.
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,18 @@ import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
|
||||||
import org.hamcrest.Matcher;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.test.util.XpathExpectationsHelper;
|
import org.springframework.test.util.XpathExpectationsHelper;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.MimeType;
|
import org.springframework.util.MimeType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XPath assertions for a {@link WebTestClient}.
|
* XPath assertions for the {@link WebTestClient}.
|
||||||
*
|
*
|
||||||
* @author Eric Deandrea
|
* @author Eric Deandrea
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public class XpathAssertions {
|
public class XpathAssertions {
|
||||||
|
|
@ -41,96 +41,87 @@ public class XpathAssertions {
|
||||||
|
|
||||||
private final XpathExpectationsHelper xpathHelper;
|
private final XpathExpectationsHelper xpathHelper;
|
||||||
|
|
||||||
XpathAssertions(WebTestClient.BodyContentSpec spec, String expression, @Nullable Map<String, String> namespaces, Object... args) throws XPathExpressionException {
|
|
||||||
|
XpathAssertions(WebTestClient.BodyContentSpec spec,
|
||||||
|
String expression, @Nullable Map<String, String> namespaces, Object... args) {
|
||||||
|
|
||||||
this.bodySpec = spec;
|
this.bodySpec = spec;
|
||||||
this.xpathHelper = new XpathExpectationsHelper(expression, namespaces, args);
|
this.xpathHelper = initXpathHelper(expression, namespaces, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static XpathExpectationsHelper initXpathHelper(
|
||||||
|
String expression, @Nullable Map<String, String> namespaces, Object[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new XpathExpectationsHelper(expression, namespaces, args);
|
||||||
|
}
|
||||||
|
catch (XPathExpressionException ex) {
|
||||||
|
throw new AssertionError("XML parsing error", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link XpathExpectationsHelper#assertString(byte[], String, String)}
|
* Delegates to {@link XpathExpectationsHelper#assertString(byte[], String, String)}
|
||||||
*/
|
*/
|
||||||
public WebTestClient.BodyContentSpec isEqualTo(String expectedValue) {
|
public WebTestClient.BodyContentSpec isEqualTo(String expectedValue) {
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertString(getResponseBody(), getDefinedEncoding(), expectedValue));
|
return assertWith(() -> this.xpathHelper.assertString(getContent(), getCharset(), expectedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link XpathExpectationsHelper#assertNumber(byte[], String, Double)}
|
* Delegates to {@link XpathExpectationsHelper#assertNumber(byte[], String, Double)}
|
||||||
*/
|
*/
|
||||||
public WebTestClient.BodyContentSpec isEqualTo(Double expectedValue) {
|
public WebTestClient.BodyContentSpec isEqualTo(Double expectedValue) {
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertNumber(getResponseBody(), getDefinedEncoding(), expectedValue));
|
return assertWith(() -> this.xpathHelper.assertNumber(getContent(), getCharset(), expectedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link XpathExpectationsHelper#assertBoolean(byte[], String, boolean)}
|
* Delegates to {@link XpathExpectationsHelper#assertBoolean(byte[], String, boolean)}
|
||||||
*/
|
*/
|
||||||
public WebTestClient.BodyContentSpec isEqualTo(boolean expectedValue) {
|
public WebTestClient.BodyContentSpec isEqualTo(boolean expectedValue) {
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertBoolean(getResponseBody(), getDefinedEncoding(), expectedValue));
|
return assertWith(() -> this.xpathHelper.assertBoolean(getContent(), getCharset(), expectedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link XpathExpectationsHelper#exists(byte[], String)}
|
* Delegates to {@link XpathExpectationsHelper#exists(byte[], String)}
|
||||||
*/
|
*/
|
||||||
public WebTestClient.BodyContentSpec exists() {
|
public WebTestClient.BodyContentSpec exists() {
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.exists(getResponseBody(), getDefinedEncoding()));
|
return assertWith(() -> this.xpathHelper.exists(getContent(), getCharset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link XpathExpectationsHelper#doesNotExist(byte[], String)}
|
* Delegates to {@link XpathExpectationsHelper#doesNotExist(byte[], String)}
|
||||||
*/
|
*/
|
||||||
public WebTestClient.BodyContentSpec doesNotExist() {
|
public WebTestClient.BodyContentSpec doesNotExist() {
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.doesNotExist(getResponseBody(), getDefinedEncoding()));
|
return assertWith(() -> this.xpathHelper.doesNotExist(getContent(), getCharset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link XpathExpectationsHelper[#assertNodeCount(byte[], String, int)}
|
* Delegates to {@link XpathExpectationsHelper[#assertNodeCount(byte[], String, int)}
|
||||||
*/
|
*/
|
||||||
public WebTestClient.BodyContentSpec nodeCount(int expectedCount) {
|
public WebTestClient.BodyContentSpec nodeCount(int expectedCount) {
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertNodeCount(getResponseBody(), getDefinedEncoding(), expectedCount));
|
return assertWith(() -> this.xpathHelper.assertNodeCount(getContent(), getCharset(), expectedCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies {@link XpathExpectationsHelper#assertNodeCount(byte[], String, Matcher)}
|
|
||||||
*/
|
|
||||||
public WebTestClient.BodyContentSpec nodeCount(Matcher<Integer> matcher) {
|
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertNodeCount(getResponseBody(), getDefinedEncoding(), matcher));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private WebTestClient.BodyContentSpec assertWith(CheckedExceptionTask task) {
|
||||||
* Applies {@link XpathExpectationsHelper#assertNode(byte[], String, Matcher)}
|
try {
|
||||||
*/
|
task.run();
|
||||||
public WebTestClient.BodyContentSpec nodeMatches(Matcher<? super Node> matcher) {
|
}
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertNode(getResponseBody(), getDefinedEncoding(), matcher));
|
catch (Exception ex) {
|
||||||
}
|
throw new AssertionError("XML parsing error", ex);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Applies {@link XpathExpectationsHelper#assertString(byte[], String, Matcher)}
|
|
||||||
*/
|
|
||||||
public WebTestClient.BodyContentSpec matchesString(Matcher<? super String> matcher) {
|
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertString(getResponseBody(), getDefinedEncoding(), matcher));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies {@link XpathExpectationsHelper#assertNumber(byte[], String, Matcher)}
|
|
||||||
*/
|
|
||||||
public WebTestClient.BodyContentSpec matchesNumber(Matcher<? super Double> matcher) {
|
|
||||||
return performXmlAssertionAndHandleError(() -> this.xpathHelper.assertNumber(getResponseBody(), getDefinedEncoding(), matcher));
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebTestClient.BodyContentSpec performXmlAssertionAndHandleError(AssertionThrowingRunnable assertion) {
|
|
||||||
assertion.run();
|
|
||||||
return this.bodySpec;
|
return this.bodySpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getResponseBody() {
|
private byte[] getContent() {
|
||||||
return getResult().getResponseBody();
|
byte[] body = this.bodySpec.returnResult().getResponseBody();
|
||||||
|
Assert.notNull(body, "Expected body content");
|
||||||
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityExchangeResult<byte[]> getResult() {
|
private String getCharset() {
|
||||||
return this.bodySpec.returnResult();
|
return Optional.of(this.bodySpec.returnResult())
|
||||||
}
|
|
||||||
|
|
||||||
private String getDefinedEncoding() {
|
|
||||||
return Optional.ofNullable(getResult())
|
|
||||||
.map(EntityExchangeResult::getResponseHeaders)
|
.map(EntityExchangeResult::getResponseHeaders)
|
||||||
.map(HttpHeaders::getContentType)
|
.map(HttpHeaders::getContentType)
|
||||||
.map(MimeType::getCharset)
|
.map(MimeType::getCharset)
|
||||||
|
|
@ -138,22 +129,14 @@ public class XpathAssertions {
|
||||||
.name();
|
.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lets us be able to use lambda expressions that could throw checked exceptions, since
|
* Lets us be able to use lambda expressions that could throw checked exceptions, since
|
||||||
* {@link XpathExpectationsHelper} throws {@link Exception} on its methods.
|
* {@link XpathExpectationsHelper} throws {@link Exception} on its methods.
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
private interface CheckedExceptionTask {
|
||||||
private interface AssertionThrowingRunnable extends Runnable {
|
|
||||||
void runThrows() throws Exception;
|
void run() throws Exception;
|
||||||
|
|
||||||
@Override
|
|
||||||
default void run() {
|
|
||||||
try {
|
|
||||||
runThrows();
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
throw new AssertionError("XML parsing error", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,18 +15,30 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.test.web.reactive.server.samples;
|
package org.springframework.test.web.reactive.server.samples;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
@XmlRootElement
|
||||||
class Person {
|
class Person {
|
||||||
|
|
||||||
private final String name;
|
private String name;
|
||||||
|
|
||||||
|
|
||||||
|
// No-arg constructor for XML
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public Person(@JsonProperty("name") String name) {
|
public Person(@JsonProperty("name") String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,24 +20,17 @@ import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
import org.hamcrest.Matchers;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -46,30 +39,32 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Samples of tests using {@link WebTestClient} with serialized XML content.
|
* Samples of tests using {@link WebTestClient} with XML content.
|
||||||
*
|
*
|
||||||
* @author Eric Deandrea
|
* @author Eric Deandrea
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public class XmlContentTests {
|
public class XmlContentTests {
|
||||||
|
|
||||||
private static final String PEOPLE_XML =
|
private static final String persons_XML =
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||||
+ "<people><people>"
|
+ "<persons>"
|
||||||
+ "<person><name>Jane</name></person>"
|
+ "<person><name>Jane</name></person>"
|
||||||
+ "<person><name>Jason</name></person>"
|
+ "<person><name>Jason</name></person>"
|
||||||
+ "<person><name>John</name></person>"
|
+ "<person><name>John</name></person>"
|
||||||
+ "</people></people>";
|
+ "</persons>";
|
||||||
|
|
||||||
|
|
||||||
private final WebTestClient client = WebTestClient.bindToController(new PersonController()).build();
|
private final WebTestClient client = WebTestClient.bindToController(new PersonController()).build();
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void xmlContent() {
|
public void xmlContent() {
|
||||||
this.client.get().uri("/persons")
|
this.client.get().uri("/persons")
|
||||||
.accept(MediaType.APPLICATION_XML)
|
.accept(MediaType.APPLICATION_XML)
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isOk()
|
.expectStatus().isOk()
|
||||||
.expectBody().xml(PEOPLE_XML);
|
.expectBody().xml(persons_XML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -80,28 +75,12 @@ public class XmlContentTests {
|
||||||
.expectStatus().isOk()
|
.expectStatus().isOk()
|
||||||
.expectBody()
|
.expectBody()
|
||||||
.xpath("/").exists()
|
.xpath("/").exists()
|
||||||
.xpath("/people").exists()
|
.xpath("/persons").exists()
|
||||||
.xpath("/people/people").exists()
|
.xpath("/persons/person").exists()
|
||||||
.xpath("/people/people/person").exists()
|
.xpath("/persons/person").nodeCount(3)
|
||||||
.xpath("/people/people/person").nodeCount(3)
|
.xpath("/persons/person[1]/name").isEqualTo("Jane")
|
||||||
.xpath("/people/people/person[1]/name").isEqualTo("Jane")
|
.xpath("/persons/person[2]/name").isEqualTo("Jason")
|
||||||
.xpath("/people/people/person[2]/name").isEqualTo("Jason")
|
.xpath("/persons/person[3]/name").isEqualTo("John");
|
||||||
.xpath("/people/people/person[3]/name").isEqualTo("John");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void xpathMatches() {
|
|
||||||
this.client.get().uri("/persons")
|
|
||||||
.accept(MediaType.APPLICATION_XML)
|
|
||||||
.exchange()
|
|
||||||
.expectStatus().isOk()
|
|
||||||
.expectBody()
|
|
||||||
.xpath("/").exists()
|
|
||||||
.xpath("/people").exists()
|
|
||||||
.xpath("/people/people").exists()
|
|
||||||
.xpath("/people/people/person").exists()
|
|
||||||
.xpath("/people/people/person").nodeCount(3)
|
|
||||||
.xpath("//person/name").matchesString(Matchers.startsWith("J"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -116,86 +95,42 @@ public class XmlContentTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postXmlContent() {
|
public void postXmlContent() {
|
||||||
|
|
||||||
|
String content =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
|
||||||
|
"<person><name>John</name></person>";
|
||||||
|
|
||||||
this.client.post().uri("/persons")
|
this.client.post().uri("/persons")
|
||||||
.contentType(MediaType.APPLICATION_XML)
|
.contentType(MediaType.APPLICATION_XML)
|
||||||
.syncBody("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><person><name>John</name></person>")
|
.syncBody(content)
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isCreated()
|
.expectStatus().isCreated()
|
||||||
.expectHeader().valueEquals(HttpHeaders.LOCATION, "/persons/John")
|
.expectHeader().valueEquals(HttpHeaders.LOCATION, "/persons/John")
|
||||||
.expectBody().isEmpty();
|
.expectBody().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@XmlRootElement
|
|
||||||
private static class Person {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
public Person() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Person(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Person name(String name) {
|
|
||||||
setName(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (this == other) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(other instanceof Person)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Person otherPerson = (Person) other;
|
|
||||||
return ObjectUtils.nullSafeEquals(this.name, otherPerson.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Person.class.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Person [name=" + this.name + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@XmlRootElement(name="people")
|
@XmlRootElement(name="persons")
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
private static class PeopleWrapper {
|
private static class PersonsWrapper {
|
||||||
|
|
||||||
@XmlElementWrapper(name="people")
|
|
||||||
@XmlElement(name="person")
|
@XmlElement(name="person")
|
||||||
private final List<Person> people = new ArrayList<>();
|
private final List<Person> persons = new ArrayList<>();
|
||||||
|
|
||||||
public PeopleWrapper() {
|
public PersonsWrapper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PeopleWrapper(List<Person> people) {
|
public PersonsWrapper(List<Person> persons) {
|
||||||
this.people.addAll(people);
|
this.persons.addAll(persons);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PeopleWrapper(Person... people) {
|
public PersonsWrapper(Person... persons) {
|
||||||
this.people.addAll(Arrays.asList(people));
|
this.persons.addAll(Arrays.asList(persons));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Person> getPeople() {
|
public List<Person> getpersons() {
|
||||||
return this.people;
|
return this.persons;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,24 +139,19 @@ public class XmlContentTests {
|
||||||
static class PersonController {
|
static class PersonController {
|
||||||
|
|
||||||
@GetMapping(produces = MediaType.APPLICATION_XML_VALUE)
|
@GetMapping(produces = MediaType.APPLICATION_XML_VALUE)
|
||||||
Mono<PeopleWrapper> getPersons() {
|
PersonsWrapper getPersons() {
|
||||||
return Mono.just(new PeopleWrapper(new Person("Jane"), new Person("Jason"), new Person("John")));
|
return new PersonsWrapper(new Person("Jane"), new Person("Jason"), new Person("John"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(path = "/{name}", produces = MediaType.APPLICATION_XML_VALUE)
|
@GetMapping(path = "/{name}", produces = MediaType.APPLICATION_XML_VALUE)
|
||||||
Mono<Person> getPerson(@PathVariable String name) {
|
Person getPerson(@PathVariable String name) {
|
||||||
return Mono.just(new Person(name));
|
return new Person(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = MediaType.APPLICATION_XML_VALUE)
|
@PostMapping(consumes = MediaType.APPLICATION_XML_VALUE)
|
||||||
Mono<ResponseEntity<Object>> savePeople(@RequestBody Flux<Person> person) {
|
ResponseEntity<Object> savepersons(@RequestBody Person person) {
|
||||||
return person
|
URI location = URI.create(String.format("/persons/%s", person.getName()));
|
||||||
.map(Person::getName)
|
return ResponseEntity.created(location).build();
|
||||||
.map(name -> String.format("/persons/%s", name))
|
|
||||||
.map(URI::create)
|
|
||||||
.map(ResponseEntity::created)
|
|
||||||
.map(ResponseEntity.BodyBuilder::build)
|
|
||||||
.next();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue