Polishing in [Rest|Web]TestClient Assertions
See gh-34428
This commit is contained in:
parent
6cc1310274
commit
88ddc9d45d
|
@ -36,12 +36,13 @@ public class CookieAssertions extends AbstractCookieAssertions<ExchangeResult, W
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertWithDiagnostics(Runnable assertion) {
|
protected MultiValueMap<String, ResponseCookie> getResponseCookies() {
|
||||||
exchangeResult.assertWithDiagnostics(assertion);
|
return getExchangeResult().getResponseCookies();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MultiValueMap<String, ResponseCookie> getResponseCookies() {
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
return exchangeResult.getResponseCookies();
|
getExchangeResult().assertWithDiagnostics(assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,13 @@ public class HeaderAssertions extends AbstractHeaderAssertions<ExchangeResult, W
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertWithDiagnostics(Runnable assertion) {
|
protected HttpHeaders getResponseHeaders() {
|
||||||
exchangeResult.assertWithDiagnostics(assertion);
|
return getExchangeResult().getResponseHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HttpHeaders getResponseHeaders() {
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
return exchangeResult.getResponseHeaders();
|
getExchangeResult().assertWithDiagnostics(assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,13 @@ public class StatusAssertions extends AbstractStatusAssertions<ExchangeResult, W
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertWithDiagnostics(Runnable assertion) {
|
protected HttpStatusCode getStatus() {
|
||||||
exchangeResult.assertWithDiagnostics(assertion);
|
return getExchangeResult().getStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HttpStatusCode getStatus() {
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
return exchangeResult.getStatus();
|
getExchangeResult().assertWithDiagnostics(assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,20 +35,23 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class XpathAssertions extends AbstractXpathAssertions<WebTestClient.BodyContentSpec> {
|
public class XpathAssertions extends AbstractXpathAssertions<WebTestClient.BodyContentSpec> {
|
||||||
|
|
||||||
XpathAssertions(WebTestClient.BodyContentSpec spec,
|
|
||||||
|
XpathAssertions(
|
||||||
|
WebTestClient.BodyContentSpec spec,
|
||||||
String expression, @Nullable Map<String, String> namespaces, Object... args) {
|
String expression, @Nullable Map<String, String> namespaces, Object... args) {
|
||||||
|
|
||||||
super(spec, expression, namespaces, args);
|
super(spec, expression, namespaces, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Optional<HttpHeaders> getResponseHeaders() {
|
protected Optional<HttpHeaders> getResponseHeaders() {
|
||||||
return Optional.of(bodySpec.returnResult())
|
return Optional.of(getBodySpec().returnResult()).map(ExchangeResult::getResponseHeaders);
|
||||||
.map(ExchangeResult::getResponseHeaders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] getContent() {
|
protected byte[] getContent() {
|
||||||
byte[] body = this.bodySpec.returnResult().getResponseBody();
|
byte[] body = getBodySpec().returnResult().getResponseBody();
|
||||||
Assert.notNull(body, "Expected body content");
|
Assert.notNull(body, "Expected body content");
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,13 @@ public class CookieAssertions extends AbstractCookieAssertions<ExchangeResult, R
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertWithDiagnostics(Runnable assertion) {
|
protected MultiValueMap<String, ResponseCookie> getResponseCookies() {
|
||||||
exchangeResult.assertWithDiagnostics(assertion);
|
return getExchangeResult().getResponseCookies();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MultiValueMap<String, ResponseCookie> getResponseCookies() {
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
return exchangeResult.getResponseCookies();
|
getExchangeResult().assertWithDiagnostics(assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.jspecify.annotations.Nullable;
|
||||||
* extracted to a representation of type {@code <T>}.
|
* extracted to a representation of type {@code <T>}.
|
||||||
*
|
*
|
||||||
* @author Rob Worsnop
|
* @author Rob Worsnop
|
||||||
|
* @since 7.0
|
||||||
* @param <T> the response body type
|
* @param <T> the response body type
|
||||||
*/
|
*/
|
||||||
public class EntityExchangeResult<T> extends ExchangeResult {
|
public class EntityExchangeResult<T> extends ExchangeResult {
|
||||||
|
|
|
@ -33,13 +33,15 @@ public class HeaderAssertions extends AbstractHeaderAssertions<ExchangeResult, R
|
||||||
super(exchangeResult, responseSpec);
|
super(exchangeResult, responseSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void assertWithDiagnostics(Runnable assertion) {
|
|
||||||
exchangeResult.assertWithDiagnostics(assertion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HttpHeaders getResponseHeaders() {
|
protected HttpHeaders getResponseHeaders() {
|
||||||
return exchangeResult.getResponseHeaders();
|
return getExchangeResult().getResponseHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
|
getExchangeResult().assertWithDiagnostics(assertion);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,13 @@ public class StatusAssertions extends AbstractStatusAssertions<ExchangeResult, R
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertWithDiagnostics(Runnable assertion) {
|
protected HttpStatusCode getStatus() {
|
||||||
exchangeResult.assertWithDiagnostics(assertion);
|
return getExchangeResult().getStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HttpStatusCode getStatus() {
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
return exchangeResult.getStatus();
|
getExchangeResult().assertWithDiagnostics(assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,12 @@ public class XpathAssertions extends AbstractXpathAssertions<RestTestClient.Body
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Optional<HttpHeaders> getResponseHeaders() {
|
protected Optional<HttpHeaders> getResponseHeaders() {
|
||||||
return Optional.of(bodySpec.returnResult())
|
return Optional.of(getBodySpec().returnResult()).map(ExchangeResult::getResponseHeaders);
|
||||||
.map(ExchangeResult::getResponseHeaders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] getContent() {
|
protected byte[] getContent() {
|
||||||
byte[] body = this.bodySpec.returnResult().getResponseBody();
|
byte[] body = getBodySpec().returnResult().getResponseBody();
|
||||||
Assert.notNull(body, "Expected body content");
|
Assert.notNull(body, "Expected body content");
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Support for testing Spring MVC applications via
|
* Support for testing Spring MVC applications via
|
||||||
* {@link org.springframework.test.web.reactive.server.WebTestClient}
|
* {@link org.springframework.test.web.servlet.client.RestTestClient} with
|
||||||
* with {@link org.springframework.test.web.servlet.MockMvc} for server request
|
* {@link org.springframework.test.web.servlet.MockMvc} for server request handling.
|
||||||
* handling.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@NullMarked
|
@NullMarked
|
||||||
|
|
|
@ -34,19 +34,42 @@ import static org.springframework.test.util.AssertionErrors.fail;
|
||||||
* Assertions on cookies of the response.
|
* Assertions on cookies of the response.
|
||||||
*
|
*
|
||||||
* @author Rob Worsnop
|
* @author Rob Worsnop
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @since 7.0
|
* @since 7.0
|
||||||
* @param <E> the type of the exchange result
|
* @param <E> the type of the exchange result
|
||||||
* @param <R> the type of the response spec
|
* @param <R> the type of the response spec
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCookieAssertions<E, R> {
|
public abstract class AbstractCookieAssertions<E, R> {
|
||||||
protected final E exchangeResult;
|
|
||||||
|
private final E exchangeResult;
|
||||||
|
|
||||||
private final R responseSpec;
|
private final R responseSpec;
|
||||||
|
|
||||||
|
|
||||||
protected AbstractCookieAssertions(E exchangeResult, R responseSpec) {
|
protected AbstractCookieAssertions(E exchangeResult, R responseSpec) {
|
||||||
this.exchangeResult = exchangeResult;
|
this.exchangeResult = exchangeResult;
|
||||||
this.responseSpec = responseSpec;
|
this.responseSpec = responseSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the exchange result.
|
||||||
|
*/
|
||||||
|
protected E getExchangeResult() {
|
||||||
|
return this.exchangeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to provide access to response cookies.
|
||||||
|
*/
|
||||||
|
protected abstract MultiValueMap<String, ResponseCookie> getResponseCookies();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to assert with diagnostics.
|
||||||
|
*/
|
||||||
|
protected abstract void assertWithDiagnostics(Runnable assertion);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expect a response cookie with the given name to match the specified value.
|
* Expect a response cookie with the given name to match the specified value.
|
||||||
*/
|
*/
|
||||||
|
@ -224,10 +247,6 @@ public abstract class AbstractCookieAssertions<E, R> {
|
||||||
return this.responseSpec;
|
return this.responseSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void assertWithDiagnostics(Runnable assertion);
|
|
||||||
|
|
||||||
protected abstract MultiValueMap<String, ResponseCookie> getResponseCookies();
|
|
||||||
|
|
||||||
private ResponseCookie getCookie(String name) {
|
private ResponseCookie getCookie(String name) {
|
||||||
ResponseCookie cookie = getResponseCookies().getFirst(name);
|
ResponseCookie cookie = getResponseCookies().getFirst(name);
|
||||||
if (cookie != null) {
|
if (cookie != null) {
|
||||||
|
|
|
@ -40,19 +40,42 @@ import static org.springframework.test.util.AssertionErrors.fail;
|
||||||
* Assertions on headers of the response.
|
* Assertions on headers of the response.
|
||||||
*
|
*
|
||||||
* @author Rob Worsnop
|
* @author Rob Worsnop
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @since 7.0
|
* @since 7.0
|
||||||
* @param <E> the type of the exchange result
|
* @param <E> the type of the exchange result
|
||||||
* @param <R> the type of the response spec
|
* @param <R> the type of the response spec
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractHeaderAssertions <E, R> {
|
public abstract class AbstractHeaderAssertions <E, R> {
|
||||||
protected final E exchangeResult;
|
|
||||||
|
private final E exchangeResult;
|
||||||
|
|
||||||
private final R responseSpec;
|
private final R responseSpec;
|
||||||
|
|
||||||
|
|
||||||
protected AbstractHeaderAssertions(E exchangeResult, R responseSpec) {
|
protected AbstractHeaderAssertions(E exchangeResult, R responseSpec) {
|
||||||
this.exchangeResult = exchangeResult;
|
this.exchangeResult = exchangeResult;
|
||||||
this.responseSpec = responseSpec;
|
this.responseSpec = responseSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the exchange result.
|
||||||
|
*/
|
||||||
|
protected E getExchangeResult() {
|
||||||
|
return this.exchangeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to provide access to response headers.
|
||||||
|
*/
|
||||||
|
protected abstract HttpHeaders getResponseHeaders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to assert with diagnostics.
|
||||||
|
*/
|
||||||
|
protected abstract void assertWithDiagnostics(Runnable assertion);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expect a header with the given name to match the specified values.
|
* Expect a header with the given name to match the specified values.
|
||||||
*/
|
*/
|
||||||
|
@ -277,10 +300,6 @@ public abstract class AbstractHeaderAssertions <E, R> {
|
||||||
return assertHeader("Location", URI.create(location), getResponseHeaders().getLocation());
|
return assertHeader("Location", URI.create(location), getResponseHeaders().getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void assertWithDiagnostics(Runnable assertion);
|
|
||||||
|
|
||||||
protected abstract HttpHeaders getResponseHeaders();
|
|
||||||
|
|
||||||
private R assertHeader(String name, @Nullable Object expected, @Nullable Object actual) {
|
private R assertHeader(String name, @Nullable Object expected, @Nullable Object actual) {
|
||||||
assertWithDiagnostics(() -> {
|
assertWithDiagnostics(() -> {
|
||||||
String message = getMessage(name);
|
String message = getMessage(name);
|
||||||
|
|
|
@ -26,6 +26,18 @@ import org.springframework.core.ParameterizedTypeReference;
|
||||||
import org.springframework.test.util.JsonPathExpectationsHelper;
|
import org.springframework.test.util.JsonPathExpectationsHelper;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for applying
|
||||||
|
* <a href="https://github.com/jayway/JsonPath">JsonPath</a> assertions
|
||||||
|
* in RestTestClient and WebTestClient.
|
||||||
|
*
|
||||||
|
* @author Rob Worsnop
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 7.0
|
||||||
|
* @param <B> the type of body spec (RestTestClient vs WebTestClient specific)
|
||||||
|
* @see <a href="https://github.com/jayway/JsonPath">https://github.com/jayway/JsonPath</a>
|
||||||
|
* @see JsonPathExpectationsHelper
|
||||||
|
*/
|
||||||
public abstract class AbstractJsonPathAssertions<B> {
|
public abstract class AbstractJsonPathAssertions<B> {
|
||||||
|
|
||||||
private final B bodySpec;
|
private final B bodySpec;
|
||||||
|
@ -34,6 +46,7 @@ public abstract class AbstractJsonPathAssertions<B> {
|
||||||
|
|
||||||
private final JsonPathExpectationsHelper pathHelper;
|
private final JsonPathExpectationsHelper pathHelper;
|
||||||
|
|
||||||
|
|
||||||
protected AbstractJsonPathAssertions(B spec, String content, String expression, @Nullable Configuration configuration) {
|
protected AbstractJsonPathAssertions(B spec, String content, String expression, @Nullable Configuration configuration) {
|
||||||
Assert.hasText(expression, "expression must not be null or empty");
|
Assert.hasText(expression, "expression must not be null or empty");
|
||||||
this.bodySpec = spec;
|
this.bodySpec = spec;
|
||||||
|
@ -41,6 +54,7 @@ public abstract class AbstractJsonPathAssertions<B> {
|
||||||
this.pathHelper = new JsonPathExpectationsHelper(expression, configuration);
|
this.pathHelper = new JsonPathExpectationsHelper(expression, configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@link JsonPathExpectationsHelper#assertValue(String, Object)}.
|
* Applies {@link JsonPathExpectationsHelper#assertValue(String, Object)}.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,18 +31,42 @@ import static org.springframework.test.util.AssertionErrors.assertNotNull;
|
||||||
* Assertions on the response status.
|
* Assertions on the response status.
|
||||||
*
|
*
|
||||||
* @author Rob Worsnop
|
* @author Rob Worsnop
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 7.0
|
||||||
* @param <E> the type of the exchange result
|
* @param <E> the type of the exchange result
|
||||||
* @param <R> the type of the response spec
|
* @param <R> the type of the response spec
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractStatusAssertions<E, R> {
|
public abstract class AbstractStatusAssertions<E, R> {
|
||||||
protected final E exchangeResult;
|
|
||||||
|
private final E exchangeResult;
|
||||||
|
|
||||||
private final R responseSpec;
|
private final R responseSpec;
|
||||||
|
|
||||||
|
|
||||||
protected AbstractStatusAssertions(E exchangeResult, R responseSpec) {
|
protected AbstractStatusAssertions(E exchangeResult, R responseSpec) {
|
||||||
this.exchangeResult = exchangeResult;
|
this.exchangeResult = exchangeResult;
|
||||||
this.responseSpec = responseSpec;
|
this.responseSpec = responseSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the exchange result.
|
||||||
|
*/
|
||||||
|
protected E getExchangeResult() {
|
||||||
|
return this.exchangeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to provide access to the response status.
|
||||||
|
*/
|
||||||
|
protected abstract HttpStatusCode getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to assert with diagnostics.
|
||||||
|
*/
|
||||||
|
protected abstract void assertWithDiagnostics(Runnable assertion);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert the response status as an {@link HttpStatusCode}.
|
* Assert the response status as an {@link HttpStatusCode}.
|
||||||
*/
|
*/
|
||||||
|
@ -226,10 +250,6 @@ public abstract class AbstractStatusAssertions<E, R> {
|
||||||
return this.responseSpec;
|
return this.responseSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void assertWithDiagnostics(Runnable assertion);
|
|
||||||
|
|
||||||
protected abstract HttpStatusCode getStatus();
|
|
||||||
|
|
||||||
private R assertStatusAndReturn(HttpStatus expected) {
|
private R assertStatusAndReturn(HttpStatus expected) {
|
||||||
assertNotNull("exchangeResult unexpectedly null", this.exchangeResult);
|
assertNotNull("exchangeResult unexpectedly null", this.exchangeResult);
|
||||||
HttpStatusCode actual = getStatus();
|
HttpStatusCode actual = getStatus();
|
||||||
|
|
|
@ -30,12 +30,24 @@ import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.test.util.XpathExpectationsHelper;
|
import org.springframework.test.util.XpathExpectationsHelper;
|
||||||
import org.springframework.util.MimeType;
|
import org.springframework.util.MimeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for applying XPath assertions in RestTestClient and WebTestClient.
|
||||||
|
*
|
||||||
|
* @author Rob Worsnop
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 7.0
|
||||||
|
* @param <B> the type of body spec (RestTestClient vs WebTestClient specific)
|
||||||
|
*/
|
||||||
public abstract class AbstractXpathAssertions<B> {
|
public abstract class AbstractXpathAssertions<B> {
|
||||||
protected final B bodySpec;
|
|
||||||
|
private final B bodySpec;
|
||||||
|
|
||||||
private final XpathExpectationsHelper xpathHelper;
|
private final XpathExpectationsHelper xpathHelper;
|
||||||
|
|
||||||
public AbstractXpathAssertions(B spec, String expression, @Nullable Map<String, String> namespaces, Object... args) {
|
|
||||||
|
public AbstractXpathAssertions(
|
||||||
|
B spec, String expression, @Nullable Map<String, String> namespaces, Object... args) {
|
||||||
|
|
||||||
this.bodySpec = spec;
|
this.bodySpec = spec;
|
||||||
this.xpathHelper = initXpathHelper(expression, namespaces, args);
|
this.xpathHelper = initXpathHelper(expression, namespaces, args);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +64,24 @@ public abstract class AbstractXpathAssertions<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the body spec.
|
||||||
|
*/
|
||||||
|
protected B getBodySpec() {
|
||||||
|
return this.bodySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to provide access to response headers.
|
||||||
|
*/
|
||||||
|
protected abstract Optional<HttpHeaders> getResponseHeaders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must implement this to provide access to the response content.
|
||||||
|
*/
|
||||||
|
protected abstract byte[] getContent();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegates to {@link XpathExpectationsHelper#assertString(byte[], String, String)}.
|
* Delegates to {@link XpathExpectationsHelper#assertString(byte[], String, String)}.
|
||||||
*/
|
*/
|
||||||
|
@ -175,9 +205,6 @@ public abstract class AbstractXpathAssertions<B> {
|
||||||
return super.hashCode();
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Optional<HttpHeaders> getResponseHeaders();
|
|
||||||
|
|
||||||
protected abstract byte[] getContent();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|
|
@ -1,145 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.test.web.reactive.server;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseCookie;
|
|
||||||
import org.springframework.mock.http.client.reactive.MockClientHttpRequest;
|
|
||||||
import org.springframework.mock.http.client.reactive.MockClientHttpResponse;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link CookieAssertions}
|
|
||||||
*
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
*/
|
|
||||||
public class CookieAssertionsTests {
|
|
||||||
|
|
||||||
private final ResponseCookie cookie = ResponseCookie.from("foo", "bar")
|
|
||||||
.maxAge(Duration.ofMinutes(30))
|
|
||||||
.domain("foo.com")
|
|
||||||
.path("/foo")
|
|
||||||
.secure(true)
|
|
||||||
.httpOnly(true)
|
|
||||||
.partitioned(true)
|
|
||||||
.sameSite("Lax")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private final CookieAssertions assertions = cookieAssertions(cookie);
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valueEquals() {
|
|
||||||
assertions.valueEquals("foo", "bar");
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.valueEquals("what?!", "bar"));
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.valueEquals("foo", "what?!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void value() {
|
|
||||||
assertions.value("foo", equalTo("bar"));
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.value("foo", equalTo("what?!")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void exists() {
|
|
||||||
assertions.exists("foo");
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.exists("what?!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void doesNotExist() {
|
|
||||||
assertions.doesNotExist("what?!");
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.doesNotExist("foo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void maxAge() {
|
|
||||||
assertions.maxAge("foo", Duration.ofMinutes(30));
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.maxAge("foo", Duration.ofMinutes(29)));
|
|
||||||
|
|
||||||
assertions.maxAge("foo", equalTo(Duration.ofMinutes(30).getSeconds()));
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.maxAge("foo", equalTo(Duration.ofMinutes(29).getSeconds())));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void domain() {
|
|
||||||
assertions.domain("foo", "foo.com");
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.domain("foo", "what.com"));
|
|
||||||
|
|
||||||
assertions.domain("foo", equalTo("foo.com"));
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.domain("foo", equalTo("what.com")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void path() {
|
|
||||||
assertions.path("foo", "/foo");
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.path("foo", "/what"));
|
|
||||||
|
|
||||||
assertions.path("foo", equalTo("/foo"));
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.path("foo", equalTo("/what")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void secure() {
|
|
||||||
assertions.secure("foo", true);
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.secure("foo", false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void httpOnly() {
|
|
||||||
assertions.httpOnly("foo", true);
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.httpOnly("foo", false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void partitioned() {
|
|
||||||
assertions.partitioned("foo", true);
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.partitioned("foo", false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sameSite() {
|
|
||||||
assertions.sameSite("foo", "Lax");
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.sameSite("foo", "Strict"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private CookieAssertions cookieAssertions(ResponseCookie cookie) {
|
|
||||||
MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, URI.create("/"));
|
|
||||||
MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK);
|
|
||||||
response.getCookies().add(cookie.getName(), cookie);
|
|
||||||
|
|
||||||
ExchangeResult result = new ExchangeResult(
|
|
||||||
request, response, Mono.empty(), Mono.empty(), Duration.ZERO, null, null);
|
|
||||||
|
|
||||||
return new CookieAssertions(result, mock());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,259 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.test.web.reactive.server;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import org.springframework.http.CacheControl;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.mock.http.client.reactive.MockClientHttpRequest;
|
|
||||||
import org.springframework.mock.http.client.reactive.MockClientHttpResponse;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
|
||||||
import static org.hamcrest.Matchers.hasItems;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link HeaderAssertions}.
|
|
||||||
*
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
* @author Sam Brannen
|
|
||||||
*/
|
|
||||||
class HeaderAssertionTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valueEquals() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("foo", "bar");
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.valueEquals("foo", "bar");
|
|
||||||
|
|
||||||
// Missing header
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.valueEquals("what?!", "bar"));
|
|
||||||
|
|
||||||
// Wrong value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.valueEquals("foo", "what?!"));
|
|
||||||
|
|
||||||
// Wrong # of values
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.valueEquals("foo", "bar", "what?!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valueEqualsWithMultipleValues() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("foo", "bar");
|
|
||||||
headers.add("foo", "baz");
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.valueEquals("foo", "bar", "baz");
|
|
||||||
|
|
||||||
// Wrong value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.valueEquals("foo", "bar", "what?!"));
|
|
||||||
|
|
||||||
// Too few values
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.valueEquals("foo", "bar"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valueMatches() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.valueMatches("Content-Type", ".*UTF-8.*");
|
|
||||||
|
|
||||||
// Wrong pattern
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.valueMatches("Content-Type", ".*ISO-8859-1.*"))
|
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header " +
|
|
||||||
"'Content-Type'=[application/json;charset=UTF-8] does not match " +
|
|
||||||
"[.*ISO-8859-1.*]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valueMatchesWithNonexistentHeader() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.valueMatches("Content-XYZ", ".*ISO-8859-1.*"))
|
|
||||||
.withMessage("Response header 'Content-XYZ' not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valuesMatch() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("foo", "value1");
|
|
||||||
headers.add("foo", "value2");
|
|
||||||
headers.add("foo", "value3");
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
assertions.valuesMatch("foo", "val.*1", "val.*2", "val.*3");
|
|
||||||
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.valuesMatch("foo", ".*", "val.*5"))
|
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage(
|
|
||||||
"Response header 'foo' has fewer or more values [value1, value2, value3] " +
|
|
||||||
"than number of patterns to match with [.*, val.*5]"));
|
|
||||||
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.valuesMatch("foo", ".*", "val.*5", ".*"))
|
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage(
|
|
||||||
"Response header 'foo'[1]='value2' does not match 'val.*5'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valueMatcher() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("foo", "bar");
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
assertions.value("foo", containsString("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void valuesMatcher() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("foo", "bar");
|
|
||||||
headers.add("foo", "baz");
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
assertions.values("foo", hasItems("bar", "baz"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void exists() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.exists("Content-Type");
|
|
||||||
|
|
||||||
// Header should not exist
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.exists("Framework"))
|
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header 'Framework' does not exist"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void doesNotExist() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.doesNotExist("Framework");
|
|
||||||
|
|
||||||
// Existing header
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.doesNotExist("Content-Type"))
|
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header " +
|
|
||||||
"'Content-Type' exists with value=[application/json;charset=UTF-8]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contentTypeCompatibleWith() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.APPLICATION_XML);
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.contentTypeCompatibleWith(MediaType.parseMediaType("application/*"));
|
|
||||||
|
|
||||||
// MediaTypes not compatible
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
|
||||||
.isThrownBy(() -> assertions.contentTypeCompatibleWith(MediaType.TEXT_XML))
|
|
||||||
.withMessage("Response header 'Content-Type'=[application/xml] is not compatible with [text/xml]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void cacheControl() {
|
|
||||||
CacheControl control = CacheControl.maxAge(1, TimeUnit.HOURS).noTransform();
|
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setCacheControl(control.getHeaderValue());
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.cacheControl(control);
|
|
||||||
|
|
||||||
// Wrong value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.cacheControl(CacheControl.noStore()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void expires() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
ZonedDateTime expires = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
|
||||||
headers.setExpires(expires);
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
assertions.expires(expires.toInstant().toEpochMilli());
|
|
||||||
|
|
||||||
// Wrong value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.expires(expires.toInstant().toEpochMilli() + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void lastModified() {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
ZonedDateTime lastModified = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
|
||||||
headers.setLastModified(lastModified.toInstant().toEpochMilli());
|
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
|
||||||
assertions.lastModified(lastModified.toInstant().toEpochMilli());
|
|
||||||
|
|
||||||
// Wrong value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.lastModified(lastModified.toInstant().toEpochMilli() + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private HeaderAssertions headerAssertions(HttpHeaders responseHeaders) {
|
|
||||||
MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, URI.create("/"));
|
|
||||||
MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK);
|
|
||||||
response.getHeaders().putAll(responseHeaders);
|
|
||||||
|
|
||||||
ExchangeResult result = new ExchangeResult(
|
|
||||||
request, response, Mono.empty(), Mono.empty(), Duration.ZERO, null, null);
|
|
||||||
|
|
||||||
return new HeaderAssertions(result, mock());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.test.web.reactive.server;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.mock.http.client.reactive.MockClientHttpRequest;
|
|
||||||
import org.springframework.mock.http.client.reactive.MockClientHttpResponse;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link StatusAssertions}.
|
|
||||||
*
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
* @author Sam Brannen
|
|
||||||
*/
|
|
||||||
class StatusAssertionTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void isEqualTo() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.isEqualTo(HttpStatus.CONFLICT);
|
|
||||||
assertions.isEqualTo(409);
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.isEqualTo(HttpStatus.REQUEST_TIMEOUT));
|
|
||||||
|
|
||||||
// Wrong status value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.isEqualTo(408));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test // gh-23630, gh-29283
|
|
||||||
void isEqualToWithCustomStatus() {
|
|
||||||
StatusAssertions assertions = statusAssertions(600);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
// assertions.isEqualTo(600);
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.isEqualTo(HttpStatus.REQUEST_TIMEOUT));
|
|
||||||
|
|
||||||
// Wrong status value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.isEqualTo(408));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void reasonEquals() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.reasonEquals("Conflict");
|
|
||||||
|
|
||||||
// Wrong reason
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.reasonEquals("Request Timeout"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries1xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONTINUE);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is1xxInformational();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(assertions::is2xxSuccessful);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries2xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.OK);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is2xxSuccessful();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(assertions::is5xxServerError);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries3xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.PERMANENT_REDIRECT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is3xxRedirection();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(assertions::is2xxSuccessful);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries4xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.BAD_REQUEST);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is4xxClientError();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(assertions::is2xxSuccessful);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries5xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is5xxServerError();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(assertions::is2xxSuccessful);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void matchesStatusValue() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.value(equalTo(409));
|
|
||||||
assertions.value(greaterThan(400));
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.value(equalTo(200)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test // gh-26658
|
|
||||||
void matchesCustomStatusValue() {
|
|
||||||
statusAssertions(600).value(equalTo(600));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private StatusAssertions statusAssertions(HttpStatus status) {
|
|
||||||
return statusAssertions(status.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatusAssertions statusAssertions(int status) {
|
|
||||||
MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, URI.create("/"));
|
|
||||||
MockClientHttpResponse response = new MockClientHttpResponse(status);
|
|
||||||
|
|
||||||
ExchangeResult result = new ExchangeResult(
|
|
||||||
request, response, Mono.empty(), Mono.empty(), Duration.ZERO, null, null);
|
|
||||||
|
|
||||||
return new StatusAssertions(result, mock());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,269 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.test.web.servlet.client;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.HttpStatusCode;
|
|
||||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
|
||||||
import static org.mockito.BDDMockito.mock;
|
|
||||||
import static org.mockito.BDDMockito.when;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link StatusAssertions}.
|
|
||||||
*
|
|
||||||
* @author Rob Worsnop
|
|
||||||
*/
|
|
||||||
class StatusAssertionTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void isEqualTo() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.isEqualTo(HttpStatus.CONFLICT);
|
|
||||||
assertions.isEqualTo(409);
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.isEqualTo(HttpStatus.REQUEST_TIMEOUT));
|
|
||||||
|
|
||||||
// Wrong status value
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.isEqualTo(408));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void isEqualToWithCustomStatus() {
|
|
||||||
StatusAssertions assertions = statusAssertions(600);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.isEqualTo(600);
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(601).isEqualTo(600));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void reasonEquals() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.reasonEquals("Conflict");
|
|
||||||
|
|
||||||
// Wrong reason
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).reasonEquals("Conflict"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries1xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONTINUE);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is1xxInformational();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(HttpStatus.OK).is1xxInformational());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries2xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.OK);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is2xxSuccessful();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is2xxSuccessful());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries3xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.PERMANENT_REDIRECT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is3xxRedirection();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is3xxRedirection());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries4xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.BAD_REQUEST);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is4xxClientError();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is4xxClientError());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusSeries5xx() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.is5xxServerError();
|
|
||||||
|
|
||||||
// Wrong series
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
statusAssertions(HttpStatus.OK).is5xxServerError());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void matchesStatusValue() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.value(equalTo(409));
|
|
||||||
assertions.value(greaterThan(400));
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
|
||||||
assertions.value(equalTo(200)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void matchesCustomStatusValue() {
|
|
||||||
statusAssertions(600).value(equalTo(600));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void consumesStatusValue() {
|
|
||||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
assertions.value((Integer value) -> assertThat(value).isEqualTo(409));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsAccepted() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.ACCEPTED).isAccepted();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isAccepted());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsNoContent() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.NO_CONTENT).isNoContent();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isNoContent());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsFound() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.FOUND).isFound();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isFound());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsSeeOther() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.SEE_OTHER).isSeeOther();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isSeeOther());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsNotModified() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.NOT_MODIFIED).isNotModified();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isNotModified());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsTemporaryRedirect() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.TEMPORARY_REDIRECT).isTemporaryRedirect();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isTemporaryRedirect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsPermanentRedirect() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.PERMANENT_REDIRECT).isPermanentRedirect();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isPermanentRedirect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsUnauthorized() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.UNAUTHORIZED).isUnauthorized();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isUnauthorized());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void statusIsForbidden() {
|
|
||||||
// Success
|
|
||||||
statusAssertions(HttpStatus.FORBIDDEN).isForbidden();
|
|
||||||
|
|
||||||
// Wrong status
|
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isForbidden());
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatusAssertions statusAssertions(HttpStatus status) {
|
|
||||||
return statusAssertions(status.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatusAssertions statusAssertions(int status) {
|
|
||||||
try {
|
|
||||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response = mock();
|
|
||||||
when(response.getStatusCode()).thenReturn(HttpStatusCode.valueOf(status));
|
|
||||||
when(response.getHeaders()).thenReturn(new HttpHeaders());
|
|
||||||
ExchangeResult result = new ExchangeResult(new MockClientHttpRequest(), response, null);
|
|
||||||
return new StatusAssertions(result, mock());
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new AssertionError(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -14,34 +14,37 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.test.web.servlet.client;
|
package org.springframework.test.web.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatusCode;
|
|
||||||
import org.springframework.http.ResponseCookie;
|
import org.springframework.http.ResponseCookie;
|
||||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.mockito.BDDMockito.mock;
|
|
||||||
import static org.mockito.BDDMockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link CookieAssertions}
|
* Tests for {@link AbstractCookieAssertions}.
|
||||||
*
|
*
|
||||||
* @author Rob Worsnop
|
* @author Rob Worsnop
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class CookieAssertionsTests {
|
public class CookieAssertionsTests {
|
||||||
|
|
||||||
private final ResponseCookie cookie = ResponseCookie.from("foo", "bar")
|
private TestCookieAssertions assertions;
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws IOException {
|
||||||
|
|
||||||
|
ResponseCookie cookie = ResponseCookie.from("foo", "bar")
|
||||||
.maxAge(Duration.ofMinutes(30))
|
.maxAge(Duration.ofMinutes(30))
|
||||||
.domain("foo.com")
|
.domain("foo.com")
|
||||||
.path("/foo")
|
.path("/foo")
|
||||||
|
@ -51,14 +54,10 @@ public class CookieAssertionsTests {
|
||||||
.sameSite("Lax")
|
.sameSite("Lax")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private CookieAssertions assertions;
|
this.assertions = initCookieAssertions(cookie);
|
||||||
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() throws IOException {
|
|
||||||
this.assertions = cookieAssertions(cookie);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void valueEquals() {
|
void valueEquals() {
|
||||||
assertions.valueEquals("foo", "bar");
|
assertions.valueEquals("foo", "bar");
|
||||||
|
@ -75,7 +74,8 @@ public class CookieAssertionsTests {
|
||||||
@Test
|
@Test
|
||||||
void valueConsumer() {
|
void valueConsumer() {
|
||||||
assertions.value("foo", input -> assertThat(input).isEqualTo("bar"));
|
assertions.value("foo", input -> assertThat(input).isEqualTo("bar"));
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.value("foo", input -> assertThat(input).isEqualTo("what?!")));
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> assertions.value("foo", input -> assertThat(input).isEqualTo("what?!")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -143,15 +143,31 @@ public class CookieAssertionsTests {
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.sameSite("foo", "Strict"));
|
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.sameSite("foo", "Strict"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TestCookieAssertions initCookieAssertions(ResponseCookie cookie) throws IOException {
|
||||||
|
return new TestCookieAssertions(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
private CookieAssertions cookieAssertions(ResponseCookie cookie) throws IOException {
|
|
||||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response = mock();
|
private static class TestCookieAssertions extends AbstractCookieAssertions<TestExchangeResult, Object> {
|
||||||
var headers = new HttpHeaders();
|
|
||||||
headers.set(HttpHeaders.SET_COOKIE, cookie.toString());
|
TestCookieAssertions(ResponseCookie cookie) {
|
||||||
when(response.getHeaders()).thenReturn(headers);
|
super(new TestExchangeResult(cookie), "");
|
||||||
when(response.getStatusCode()).thenReturn(HttpStatusCode.valueOf(200));
|
}
|
||||||
ExchangeResult result = new ExchangeResult(new MockClientHttpRequest(), response, null);
|
|
||||||
return new CookieAssertions(result, mock());
|
@Override
|
||||||
|
protected MultiValueMap<String, ResponseCookie> getResponseCookies() {
|
||||||
|
ResponseCookie cookie = getExchangeResult().cookie();
|
||||||
|
return MultiValueMap.fromSingleValue(Map.of(cookie.getName(), cookie));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
|
assertion.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private record TestExchangeResult(ResponseCookie cookie) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,9 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.test.web.servlet.client;
|
package org.springframework.test.web.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
@ -27,21 +26,17 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.http.CacheControl;
|
import org.springframework.http.CacheControl;
|
||||||
import org.springframework.http.ContentDisposition;
|
import org.springframework.http.ContentDisposition;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatusCode;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.hasItems;
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
import static org.mockito.BDDMockito.mock;
|
|
||||||
import static org.mockito.BDDMockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link HeaderAssertions}.
|
* Tests for {@link AbstractHeaderAssertions}.
|
||||||
*
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @author Rob Worsnop
|
* @author Rob Worsnop
|
||||||
*/
|
*/
|
||||||
class HeaderAssertionTests {
|
class HeaderAssertionTests {
|
||||||
|
@ -51,7 +46,7 @@ class HeaderAssertionTests {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add("foo", "bar");
|
headers.add("foo", "bar");
|
||||||
headers.add("age", "22");
|
headers.add("age", "22");
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.valueEquals("foo", "bar");
|
assertions.valueEquals("foo", "bar");
|
||||||
|
@ -60,16 +55,16 @@ class HeaderAssertionTests {
|
||||||
assertions.valueEquals("age", 22);
|
assertions.valueEquals("age", 22);
|
||||||
|
|
||||||
// Missing header
|
// Missing header
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.valueEquals("what?!", "bar"));
|
.isThrownBy(() -> assertions.valueEquals("what?!", "bar"));
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.valueEquals("foo", "what?!"));
|
.isThrownBy(() -> assertions.valueEquals("foo", "what?!"));
|
||||||
|
|
||||||
// Wrong # of values
|
// Wrong # of values
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.valueEquals("foo", "bar", "what?!"));
|
.isThrownBy(() -> assertions.valueEquals("foo", "bar", "what?!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -77,25 +72,25 @@ class HeaderAssertionTests {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add("foo", "bar");
|
headers.add("foo", "bar");
|
||||||
headers.add("foo", "baz");
|
headers.add("foo", "baz");
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.valueEquals("foo", "bar", "baz");
|
assertions.valueEquals("foo", "bar", "baz");
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.valueEquals("foo", "bar", "what?!"));
|
.isThrownBy(() -> assertions.valueEquals("foo", "bar", "what?!"));
|
||||||
|
|
||||||
// Too few values
|
// Too few values
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.valueEquals("foo", "bar"));
|
.isThrownBy(() -> assertions.valueEquals("foo", "bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void valueMatches() {
|
void valueMatches() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.valueMatches("Content-Type", ".*UTF-8.*");
|
assertions.valueMatches("Content-Type", ".*UTF-8.*");
|
||||||
|
@ -112,7 +107,7 @@ class HeaderAssertionTests {
|
||||||
void valueMatchesWithNonexistentHeader() {
|
void valueMatchesWithNonexistentHeader() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
assertThatExceptionOfType(AssertionError.class)
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
.isThrownBy(() -> assertions.valueMatches("Content-XYZ", ".*ISO-8859-1.*"))
|
.isThrownBy(() -> assertions.valueMatches("Content-XYZ", ".*ISO-8859-1.*"))
|
||||||
|
@ -125,7 +120,7 @@ class HeaderAssertionTests {
|
||||||
headers.add("foo", "value1");
|
headers.add("foo", "value1");
|
||||||
headers.add("foo", "value2");
|
headers.add("foo", "value2");
|
||||||
headers.add("foo", "value3");
|
headers.add("foo", "value3");
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
assertions.valuesMatch("foo", "val.*1", "val.*2", "val.*3");
|
assertions.valuesMatch("foo", "val.*1", "val.*2", "val.*3");
|
||||||
|
|
||||||
|
@ -145,7 +140,7 @@ class HeaderAssertionTests {
|
||||||
void valueMatcher() {
|
void valueMatcher() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add("foo", "bar");
|
headers.add("foo", "bar");
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
assertions.value("foo", containsString("a"));
|
assertions.value("foo", containsString("a"));
|
||||||
}
|
}
|
||||||
|
@ -155,7 +150,7 @@ class HeaderAssertionTests {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add("foo", "bar");
|
headers.add("foo", "bar");
|
||||||
headers.add("foo", "baz");
|
headers.add("foo", "baz");
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
assertions.values("foo", hasItems("bar", "baz"));
|
assertions.values("foo", hasItems("bar", "baz"));
|
||||||
}
|
}
|
||||||
|
@ -164,14 +159,14 @@ class HeaderAssertionTests {
|
||||||
void exists() {
|
void exists() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.exists("Content-Type");
|
assertions.exists("Content-Type");
|
||||||
|
|
||||||
// Header should not exist
|
// Header should not exist
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.exists("Framework"))
|
.isThrownBy(() -> assertions.exists("Framework"))
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header 'Framework' does not exist"));
|
.satisfies(ex -> assertThat(ex).hasMessage("Response header 'Framework' does not exist"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,14 +174,14 @@ class HeaderAssertionTests {
|
||||||
void doesNotExist() {
|
void doesNotExist() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.doesNotExist("Framework");
|
assertions.doesNotExist("Framework");
|
||||||
|
|
||||||
// Existing header
|
// Existing header
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.doesNotExist("Content-Type"))
|
.isThrownBy(() -> assertions.doesNotExist("Content-Type"))
|
||||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header " +
|
.satisfies(ex -> assertThat(ex).hasMessage("Response header " +
|
||||||
"'Content-Type' exists with value=[application/json;charset=UTF-8]"));
|
"'Content-Type' exists with value=[application/json;charset=UTF-8]"));
|
||||||
}
|
}
|
||||||
|
@ -195,7 +190,7 @@ class HeaderAssertionTests {
|
||||||
void contentTypeCompatibleWith() {
|
void contentTypeCompatibleWith() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.APPLICATION_XML);
|
headers.setContentType(MediaType.APPLICATION_XML);
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.contentTypeCompatibleWith(MediaType.parseMediaType("application/*"));
|
assertions.contentTypeCompatibleWith(MediaType.parseMediaType("application/*"));
|
||||||
|
@ -211,14 +206,13 @@ class HeaderAssertionTests {
|
||||||
void location() {
|
void location() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setLocation(URI.create("http://localhost:8080/"));
|
headers.setLocation(URI.create("http://localhost:8080/"));
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.location("http://localhost:8080/");
|
assertions.location("http://localhost:8080/");
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.location("http://localhost:8081/"));
|
||||||
assertions.location("http://localhost:8081/"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -227,51 +221,50 @@ class HeaderAssertionTests {
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setCacheControl(control.getHeaderValue());
|
headers.setCacheControl(control.getHeaderValue());
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
assertions.cacheControl(control);
|
assertions.cacheControl(control);
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.cacheControl(CacheControl.noStore()));
|
.isThrownBy(() -> assertions.cacheControl(CacheControl.noStore()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contentDisposition() {
|
void contentDisposition() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentDispositionFormData("foo", "bar");
|
headers.setContentDispositionFormData("foo", "bar");
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
assertions.contentDisposition(ContentDisposition.formData().name("foo").filename("bar").build());
|
assertions.contentDisposition(ContentDisposition.formData().name("foo").filename("bar").build());
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.contentDisposition(ContentDisposition.attachment().build()));
|
.isThrownBy(() -> assertions.contentDisposition(ContentDisposition.attachment().build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contentLength() {
|
void contentLength() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentLength(100);
|
headers.setContentLength(100);
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
assertions.contentLength(100);
|
assertions.contentLength(100);
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.contentLength(200));
|
||||||
assertions.contentLength(200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contentType() {
|
void contentType() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
assertions.contentType(MediaType.APPLICATION_JSON);
|
assertions.contentType(MediaType.APPLICATION_JSON);
|
||||||
assertions.contentType("application/json");
|
assertions.contentType("application/json");
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.contentType(MediaType.APPLICATION_XML));
|
.isThrownBy(() -> assertions.contentType(MediaType.APPLICATION_XML));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,12 +273,12 @@ class HeaderAssertionTests {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
ZonedDateTime expires = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
ZonedDateTime expires = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
||||||
headers.setExpires(expires);
|
headers.setExpires(expires);
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
assertions.expires(expires.toInstant().toEpochMilli());
|
assertions.expires(expires.toInstant().toEpochMilli());
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.expires(expires.toInstant().toEpochMilli() + 1));
|
.isThrownBy(() -> assertions.expires(expires.toInstant().toEpochMilli() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -293,37 +286,45 @@ class HeaderAssertionTests {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
ZonedDateTime lastModified = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
ZonedDateTime lastModified = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
||||||
headers.setLastModified(lastModified.toInstant().toEpochMilli());
|
headers.setLastModified(lastModified.toInstant().toEpochMilli());
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
assertions.lastModified(lastModified.toInstant().toEpochMilli());
|
assertions.lastModified(lastModified.toInstant().toEpochMilli());
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.lastModified(lastModified.toInstant().toEpochMilli() + 1));
|
.isThrownBy(() -> assertions.lastModified(lastModified.toInstant().toEpochMilli() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void equalsDate() {
|
void equalsDate() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setDate("foo", 1000);
|
headers.setDate("foo", 1000);
|
||||||
HeaderAssertions assertions = headerAssertions(headers);
|
TestHeaderAssertions assertions = new TestHeaderAssertions(headers);
|
||||||
assertions.valueEqualsDate("foo", 1000);
|
assertions.valueEqualsDate("foo", 1000);
|
||||||
|
|
||||||
// Wrong value
|
// Wrong value
|
||||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
assertions.valueEqualsDate("foo", 2000));
|
.isThrownBy(() -> assertions.valueEqualsDate("foo", 2000));
|
||||||
}
|
}
|
||||||
|
|
||||||
private HeaderAssertions headerAssertions(HttpHeaders responseHeaders) {
|
|
||||||
try {
|
private static class TestHeaderAssertions extends AbstractHeaderAssertions<TestExchangeResult, Object> {
|
||||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response = mock();
|
|
||||||
when(response.getStatusCode()).thenReturn(HttpStatusCode.valueOf(200));
|
TestHeaderAssertions(HttpHeaders headers) {
|
||||||
when(response.getHeaders()).thenReturn(responseHeaders);
|
super(new TestExchangeResult(headers), "");
|
||||||
ExchangeResult result = new ExchangeResult(new MockClientHttpRequest(), response, null);
|
|
||||||
return new HeaderAssertions(result, mock());
|
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
|
||||||
throw new IllegalStateException(ex);
|
@Override
|
||||||
|
protected HttpHeaders getResponseHeaders() {
|
||||||
|
return getExchangeResult().headers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
|
assertion.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private record TestExchangeResult(HttpHeaders headers) {}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.web.support;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AbstractStatusAssertions}.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Rob Worsnop
|
||||||
|
*/
|
||||||
|
class StatusAssertionTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isEqualTo() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.CONFLICT);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.isEqualTo(HttpStatus.CONFLICT);
|
||||||
|
assertions.isEqualTo(409);
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> assertions.isEqualTo(HttpStatus.REQUEST_TIMEOUT));
|
||||||
|
|
||||||
|
// Wrong status value
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> assertions.isEqualTo(408));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isEqualToWithCustomStatus() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(600);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.isEqualTo(600);
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(601).isEqualTo(600));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reasonEquals() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.CONFLICT);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.reasonEquals("Conflict");
|
||||||
|
|
||||||
|
// Wrong reason
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).reasonEquals("Conflict"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusSeries1xx() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.CONTINUE);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.is1xxInformational();
|
||||||
|
|
||||||
|
// Wrong series
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.OK).is1xxInformational());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusSeries2xx() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.OK);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.is2xxSuccessful();
|
||||||
|
|
||||||
|
// Wrong series
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is2xxSuccessful());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusSeries3xx() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.PERMANENT_REDIRECT);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.is3xxRedirection();
|
||||||
|
|
||||||
|
// Wrong series
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is3xxRedirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusSeries4xx() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.BAD_REQUEST);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.is4xxClientError();
|
||||||
|
|
||||||
|
// Wrong series
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is4xxClientError());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusSeries5xx() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.is5xxServerError();
|
||||||
|
|
||||||
|
// Wrong series
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.OK).is5xxServerError());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matchesStatusValue() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.CONFLICT);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.value(equalTo(409));
|
||||||
|
assertions.value(greaterThan(400));
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.value(equalTo(200)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matchesCustomStatusValue() {
|
||||||
|
new TestStatusAssertions(600).value(equalTo(600));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void consumesStatusValue() {
|
||||||
|
TestStatusAssertions assertions = new TestStatusAssertions(HttpStatus.CONFLICT);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
assertions.value((Integer value) -> assertThat(value).isEqualTo(409));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsAccepted() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.ACCEPTED).isAccepted();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isAccepted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsNoContent() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.NO_CONTENT).isNoContent();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isNoContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsFound() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.FOUND).isFound();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isFound());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsSeeOther() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.SEE_OTHER).isSeeOther();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isSeeOther());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsNotModified() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.NOT_MODIFIED).isNotModified();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isNotModified());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsTemporaryRedirect() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.TEMPORARY_REDIRECT).isTemporaryRedirect();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isTemporaryRedirect());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsPermanentRedirect() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.PERMANENT_REDIRECT).isPermanentRedirect();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isPermanentRedirect());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsUnauthorized() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.UNAUTHORIZED).isUnauthorized();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isUnauthorized());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void statusIsForbidden() {
|
||||||
|
// Success
|
||||||
|
new TestStatusAssertions(HttpStatus.FORBIDDEN).isForbidden();
|
||||||
|
|
||||||
|
// Wrong status
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> new TestStatusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isForbidden());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class TestStatusAssertions extends AbstractStatusAssertions<TestExchangeResult, Object> {
|
||||||
|
|
||||||
|
TestStatusAssertions(HttpStatus status) {
|
||||||
|
this(status.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TestStatusAssertions(int status) {
|
||||||
|
super(new TestExchangeResult(HttpStatusCode.valueOf(status)), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpStatusCode getStatus() {
|
||||||
|
return getExchangeResult().status();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assertWithDiagnostics(Runnable assertion) {
|
||||||
|
assertion.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private record TestExchangeResult(HttpStatusCode status) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -98,7 +98,7 @@
|
||||||
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]context[\\/]aot[\\/]samples[\\/]web[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]context[\\/]aot[\\/]samples[\\/]web[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
||||||
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]context[\\/]junit[\\/]jupiter[\\/]web[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]context[\\/]junit[\\/]jupiter[\\/]web[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
||||||
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]util[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]util[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
||||||
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]web[\\/](client|reactive|servlet)[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]web[\\/](client|reactive|servlet|support)[\\/].+Tests" checks="IllegalImport" id="bannedHamcrestImports"/>
|
||||||
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]context[\\/](aot|junit4)" checks="SpringJUnit5"/>
|
<suppress files="src[\\/]test[\\/]java[\\/]org[\\/]springframework[\\/]test[\\/]context[\\/](aot|junit4)" checks="SpringJUnit5"/>
|
||||||
<suppress files="org[\\/]springframework[\\/]test[\\/]context[\\/].+[\\/](ExpectedExceptionSpringRunnerTests|StandardJUnit4FeaturesTests|ProgrammaticTxMgmtTestNGTests)" checks="RegexpSinglelineJava" id="expectedExceptionAnnotation"/>
|
<suppress files="org[\\/]springframework[\\/]test[\\/]context[\\/].+[\\/](ExpectedExceptionSpringRunnerTests|StandardJUnit4FeaturesTests|ProgrammaticTxMgmtTestNGTests)" checks="RegexpSinglelineJava" id="expectedExceptionAnnotation"/>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue