Refactor ExchangeActions
This commit is contained in:
@@ -17,9 +17,13 @@ package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -27,8 +31,10 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.test.util.AssertionErrors;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
|
||||
|
||||
/**
|
||||
* An API to apply assertion and other actions against a performed exchange.
|
||||
* Entry point for applying assertions and actions on a performed exchange.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
@@ -69,39 +75,49 @@ public final class ExchangeActions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert options for any response header specified by name.
|
||||
* @return options for asserting headers
|
||||
* Assert value(s) of the specified header name.
|
||||
* @param headerName the header name
|
||||
* @return options for asserting the header value(s)
|
||||
*/
|
||||
public StringMultiValueMapEntryAssertions assertHeader(String headerName) {
|
||||
public ResponseHeaderAssertions assertHeader(String headerName) {
|
||||
HttpHeaders headers = getResponse().headers().asHttpHeaders();
|
||||
return new StringMultiValueMapEntryAssertions(this, headerName, headers, "Response header");
|
||||
List<String> values = headers.getOrDefault(headerName, Collections.emptyList());
|
||||
return new ResponseHeaderAssertions(this, headerName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response is empty.
|
||||
* Assert the response does not have any content.
|
||||
*/
|
||||
public void assertNoContent() {
|
||||
Flux<?> body = getResponse().bodyToFlux(ByteBuffer.class);
|
||||
StepVerifier.create(body).expectComplete().verify(getResponseTimeout());
|
||||
public ExchangeActions assertBodyIsEmpty() {
|
||||
Flux<?> body = this.exchangeInfo.getResponse().bodyToFlux(ByteBuffer.class);
|
||||
StepVerifier.create(body).expectComplete().verify(this.exchangeInfo.getResponseTimeout());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the content of the response.
|
||||
* @param entityType the type of entity to decode the response as
|
||||
* @param <T> the type of entity
|
||||
* @return further options for asserting response entities
|
||||
*/
|
||||
public <T> ResponseContentAssertions<T> assertEntity(Class<T> entityType) {
|
||||
return new ResponseContentAssertions<T>(this.exchangeInfo, ResolvableType.forClass(entityType));
|
||||
public <T> ResponseEntityAssertions<T> assertEntity(Class<T> entityType) {
|
||||
return assertEntity(ResolvableType.forClass(entityType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #assertEntity(Class)} with a {@link ResolvableType}.
|
||||
* @param entityType the type of entity to decode the response as
|
||||
* Assert the content of the response.
|
||||
* @return further options for asserting response entities
|
||||
*/
|
||||
public <T> ResponseContentAssertions<T> assertEntity(ResolvableType entityType) {
|
||||
return new ResponseContentAssertions<T>(this.exchangeInfo, entityType);
|
||||
public <T> ResponseEntityAssertions<T> assertEntity(ResolvableType entityType) {
|
||||
return new ResponseEntityAssertions<T>(this, this.exchangeInfo, entityType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response decoded as a Map of the given key and value types.
|
||||
*/
|
||||
public <K, V> MapAssertions<K, V> assertBodyAsMap(Class<K> keyType, Class<V> valueType) {
|
||||
ResolvableType type = ResolvableType.forClassWithGenerics(Map.class, keyType, valueType);
|
||||
Mono<Map<K, V>> mono = this.exchangeInfo.getResponse().body(toMono(type));
|
||||
Map<K, V> map = mono.block(this.exchangeInfo.getResponseTimeout());
|
||||
return new MapAssertions<>(this, map, "Response body map");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,4 +148,11 @@ public final class ExchangeActions {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link ExchangeInfo} for direct access to request and response.
|
||||
*/
|
||||
public ExchangeInfo andReturn() {
|
||||
return this.exchangeInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||
|
||||
/**
|
||||
* Assertions on a collection of values.
|
||||
*
|
||||
* @param <E> the type of element values in the collection
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ListAssertions<E> extends ObjectAssertions<List<E>, ListAssertions<E>> {
|
||||
|
||||
|
||||
protected ListAssertions(ExchangeActions actions, List<E> collection, String errorPrefix) {
|
||||
super(actions, collection, errorPrefix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the size of the collection.
|
||||
*/
|
||||
public ListAssertions<E> hasSize(int size) {
|
||||
assertEquals(getErrorPrefix() + " count", size, getValue().size());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the collection contains all of the given values.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListAssertions<E> contains(E... entities) {
|
||||
Arrays.stream(entities).forEach(entity -> {
|
||||
boolean result = getValue().contains(entity);
|
||||
assertTrue(getErrorPrefix() + " do not contain " + entity, result);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the collection does not contain any of the given values.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListAssertions<E> doesNotContain(E... entities) {
|
||||
Arrays.stream(entities).forEach(entity -> {
|
||||
boolean result = !getValue().contains(entity);
|
||||
assertTrue(getErrorPrefix() + " should not contain " + entity, result);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||
|
||||
/**
|
||||
* Assertions on a map of values.
|
||||
*
|
||||
* @param <K, V> the type of values in map
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MapAssertions<K, V> extends ObjectAssertions<Map<K, V>, MapAssertions<K, V>> {
|
||||
|
||||
|
||||
protected MapAssertions(ExchangeActions actions, Map<K, V> map, String errorPrefix) {
|
||||
super(actions, map, errorPrefix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the size of the map.
|
||||
*/
|
||||
public MapAssertions<K, V> hasSize(int size) {
|
||||
assertEquals(getErrorPrefix() + " count", size, getValue().size());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the map contains all of the given values.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapAssertions<K, V> contains(K key, V value) {
|
||||
V actual = getValue().get(key);
|
||||
assertEquals(getErrorPrefix() + " do not contain " + value, value, actual);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the map contains all of the given keys.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapAssertions<K, V> containsKeys(K... keys) {
|
||||
Arrays.stream(keys).forEach(key -> {
|
||||
boolean result = getValue().containsKey(key);
|
||||
assertTrue(getErrorPrefix() + " does not contain key " + key, result);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the map contains all of the given keys.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapAssertions<K, V> containsValues(V... values) {
|
||||
Arrays.stream(values).forEach(value -> {
|
||||
boolean result = getValue().containsValue(value);
|
||||
assertTrue(getErrorPrefix() + " does not contain value " + value, result);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the map does not contain any of the given keys.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapAssertions<K, V> doesNotContain(K... keys) {
|
||||
Arrays.stream(keys).forEach(key -> {
|
||||
boolean result = !getValue().containsKey(key);
|
||||
assertTrue(getErrorPrefix() + " should not contain " + key, result);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.test.util.AssertionErrors;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||
|
||||
/**
|
||||
* Assertions on an Object.
|
||||
*
|
||||
* @param <V> the type of Object to apply assertions to
|
||||
* @param <S> assertion method return type
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ObjectAssertions<V, S extends ObjectAssertions<V, S>> {
|
||||
|
||||
private final ExchangeActions exchangeActions;
|
||||
|
||||
private V value;
|
||||
|
||||
private final Supplier<V> valueSupplier;
|
||||
|
||||
private final String errorPrefix;
|
||||
|
||||
|
||||
protected ObjectAssertions(ExchangeActions exchangeActions, V value, String errorPrefix) {
|
||||
this(exchangeActions, () -> value, errorPrefix);
|
||||
}
|
||||
|
||||
protected ObjectAssertions(ExchangeActions exchangeActions, Supplier<V> valueSupplier, String errorPrefix) {
|
||||
this.exchangeActions = exchangeActions;
|
||||
this.valueSupplier = valueSupplier;
|
||||
this.errorPrefix = errorPrefix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the actual value is equal to the given expected value.
|
||||
*/
|
||||
public <T extends S> T isEqualTo(V expected) {
|
||||
assertEquals(this.errorPrefix, expected, getValue());
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the actual value is not equal to the expected value.
|
||||
*/
|
||||
public <T extends S> T isNotEqualTo(V expected) {
|
||||
assertEquals(this.errorPrefix, expected, getValue());
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom assertions on the Object value with the help of
|
||||
* {@link AssertionErrors} or an assertion library such as AssertJ.
|
||||
* <p>Consider using statically imported methods for creating the assertion
|
||||
* consumer to improve readability of tests.
|
||||
* @param assertionConsumer consumer that will apply assertions.
|
||||
*/
|
||||
public <T extends S> T andAssert(Consumer<V> assertionConsumer) {
|
||||
assertionConsumer.accept(getValue());
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom actions on the Object value.
|
||||
* <p>Consider using statically imported methods for creating the assertion
|
||||
* consumer to improve readability of tests.
|
||||
* @param consumer consumer that will apply the custom action
|
||||
*/
|
||||
public <T extends S> T andDo(Consumer<V> consumer) {
|
||||
consumer.accept(getValue());
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue with more assertions or actions on the response.
|
||||
*/
|
||||
public ExchangeActions and() {
|
||||
return this.exchangeActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link ExchangeInfo} for direct access to request and response.
|
||||
*/
|
||||
public ExchangeInfo andReturn() {
|
||||
return this.exchangeActions.andReturn();
|
||||
}
|
||||
|
||||
|
||||
// Protected methods for sub-classes
|
||||
|
||||
protected ExchangeActions getExchangeActions() {
|
||||
return this.exchangeActions;
|
||||
}
|
||||
|
||||
protected String getErrorPrefix() {
|
||||
return this.errorPrefix;
|
||||
}
|
||||
|
||||
protected V getValue() {
|
||||
if (this.value == null) {
|
||||
this.value = this.valueSupplier.get();
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends S> T self() {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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 reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
|
||||
|
||||
/**
|
||||
* Provides options for asserting the content of the response.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ResponseContentAssertions<T> extends ResponseEntityAssertions<T> {
|
||||
|
||||
|
||||
ResponseContentAssertions(ExchangeInfo exchangeInfo, ResolvableType entityType) {
|
||||
super(exchangeInfo, entityType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the response as a collection of entities.
|
||||
*/
|
||||
public ResponseEntityCollectionAssertions<T> collection() {
|
||||
return new ResponseEntityCollectionAssertions<>(getExchangeInfo(), getEntityType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response using a {@link StepVerifier}.
|
||||
*/
|
||||
public StepVerifier.FirstStep<T> stepVerifier() {
|
||||
Flux<T> flux = getExchangeInfo().getResponse().body(toFlux(getEntityType()));
|
||||
return StepVerifier.create(flux);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,91 +15,59 @@
|
||||
*/
|
||||
package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.test.util.AssertionErrors;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
|
||||
|
||||
/**
|
||||
* Provides methods for asserting the response body as a single entity.
|
||||
* Assertions on the response body decoded as a single entity.
|
||||
*
|
||||
* @param <T> the response entity type
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
* @sine 5.0
|
||||
*/
|
||||
public class ResponseEntityAssertions<T> {
|
||||
public class ResponseEntityAssertions<T> extends ObjectAssertions<T, ResponseEntityAssertions<T>> {
|
||||
|
||||
private final ExchangeInfo exchangeInfo;
|
||||
|
||||
private final ResolvableType entityType;
|
||||
|
||||
private T entity;
|
||||
|
||||
|
||||
ResponseEntityAssertions(ExchangeInfo info, ResolvableType entityType) {
|
||||
ResponseEntityAssertions(ExchangeActions actions, ExchangeInfo info, ResolvableType entityType) {
|
||||
super(actions, () -> initEntity(info, entityType), "Response body");
|
||||
this.exchangeInfo = info;
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
|
||||
protected ExchangeInfo getExchangeInfo() {
|
||||
return this.exchangeInfo;
|
||||
}
|
||||
|
||||
protected ResolvableType getEntityType() {
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
private T resolveEntity() {
|
||||
if (this.entity == null) {
|
||||
Mono<T> mono = this.exchangeInfo.getResponse().body(toMono(entityType));
|
||||
this.entity = mono.block(this.exchangeInfo.getResponseTimeout());
|
||||
}
|
||||
return this.entity;
|
||||
private static <T> T initEntity(ExchangeInfo exchangeInfo, ResolvableType entityType) {
|
||||
Mono<T> mono = exchangeInfo.getResponse().body(toMono(entityType));
|
||||
return mono.block(exchangeInfo.getResponseTimeout());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the response entity is equal to the given expected entity.
|
||||
* Assert the response decoded as a Collection of entities of the given type.
|
||||
*/
|
||||
public ResponseEntityAssertions<T> isEqualTo(T expected) {
|
||||
assertEquals("Response body", expected, resolveEntity());
|
||||
return this;
|
||||
public ListAssertions<T> list() {
|
||||
Flux<T> flux = this.exchangeInfo.getResponse().body(toFlux(this.entityType));
|
||||
List<T> list = flux.collectList().block(this.exchangeInfo.getResponseTimeout());
|
||||
return new ListAssertions<T>(getExchangeActions(), list, "Response entity collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response entity is not equal to the given expected entity.
|
||||
* Assert the response content using a {@link StepVerifier}.
|
||||
*/
|
||||
public ResponseEntityAssertions<T> isNotEqualTo(T expected) {
|
||||
assertEquals("Response body", expected, resolveEntity());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom assertions on the response entity with the help of
|
||||
* {@link AssertionErrors} or an assertion library such as AssertJ.
|
||||
* <p>Consider using statically imported methods for creating the assertion
|
||||
* consumer to improve readability of tests.
|
||||
* @param assertionConsumer consumer that will apply assertions.
|
||||
*/
|
||||
public ResponseEntityAssertions<T> andAssert(Consumer<T> assertionConsumer) {
|
||||
assertionConsumer.accept(resolveEntity());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom actions on the response entity collection.
|
||||
* <p>Consider using statically imported methods for creating the assertion
|
||||
* consumer to improve readability of tests.
|
||||
* @param consumer consumer that will apply the custom action
|
||||
*/
|
||||
public ResponseEntityAssertions<T> andDo(Consumer<T> consumer) {
|
||||
consumer.accept(resolveEntity());
|
||||
return this;
|
||||
public StepVerifier.FirstStep<T> stepVerifier() {
|
||||
Flux<T> flux = this.exchangeInfo.getResponse().body(toFlux(this.entityType));
|
||||
return StepVerifier.create(flux);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.test.util.AssertionErrors;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
|
||||
|
||||
/**
|
||||
* Provides methods for asserting the response body as a collection of entities.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ResponseEntityCollectionAssertions<T> {
|
||||
|
||||
private final Collection<T> entities;
|
||||
|
||||
|
||||
ResponseEntityCollectionAssertions(ExchangeInfo info, ResolvableType entityType) {
|
||||
Flux<T> flux = info.getResponse().body(toFlux(entityType));
|
||||
this.entities = flux.collectList().block(info.getResponseTimeout());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the number of entities.
|
||||
*/
|
||||
public ResponseEntityCollectionAssertions<T> hasSize(int size) {
|
||||
assertEquals("Response entities count", size, this.entities.size());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the response contains all of the given entities.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ResponseEntityCollectionAssertions<T> contains(T... entities) {
|
||||
Arrays.stream(entities).forEach(entity ->
|
||||
assertTrue("Response does not contain " + entity, this.entities.contains(entity)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the response does not contain any of the given entities.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ResponseEntityCollectionAssertions<T> doesNotContain(T... entities) {
|
||||
Arrays.stream(entities).forEach(entity ->
|
||||
assertTrue("Response should not contain " + entity, !this.entities.contains(entity)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom assertions on the response entity collection with the help of
|
||||
* {@link AssertionErrors} or an assertion library such as AssertJ.
|
||||
* <p>Consider using statically imported methods for creating the assertion
|
||||
* consumer to improve readability of tests.
|
||||
* @param assertionConsumer consumer that will apply assertions.
|
||||
*/
|
||||
public ResponseEntityCollectionAssertions<T> andAssert(Consumer<Collection<T>> assertionConsumer) {
|
||||
assertionConsumer.accept(this.entities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom actions on the response entity collection.
|
||||
* <p>Consider using statically imported methods for creating the assertion
|
||||
* consumer to improve readability of tests.
|
||||
* @param consumer consumer that will apply the custom action
|
||||
*/
|
||||
public ResponseEntityCollectionAssertions<T> andDo(Consumer<Collection<T>> consumer) {
|
||||
consumer.accept(this.entities);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.List;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Assertions on the values of a specific header.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ResponseHeaderAssertions extends StringAssertions {
|
||||
|
||||
private final List<String> values;
|
||||
|
||||
|
||||
ResponseHeaderAssertions(ExchangeActions actions, String headerName, List<String> values) {
|
||||
super(actions, initHeaderValue(values), "Response header [" + headerName + "]");
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
private static String initHeaderValue(List<String> values) {
|
||||
return CollectionUtils.isEmpty(values) ? null : values.get(0);
|
||||
}
|
||||
|
||||
|
||||
public ListAssertions<String> values() {
|
||||
return new ListAssertions<>(getExchangeActions(), this.values, getErrorPrefix());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.ContentDisposition;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -23,7 +26,7 @@ import org.springframework.http.MediaType;
|
||||
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||
|
||||
/**
|
||||
* Provides methods for asserting specific, commonly used response headers.
|
||||
* Assertions on specific, commonly used response headers.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||
|
||||
/**
|
||||
* Assertions on a String value.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class StringAssertions extends ObjectAssertions<String, StringAssertions> {
|
||||
|
||||
|
||||
public StringAssertions(ExchangeActions exchangeActions, String value, String errorPrefix) {
|
||||
super(exchangeActions, value, errorPrefix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The value {@link String#contains contains} the given sub-strings.
|
||||
* @param values the values to match
|
||||
*/
|
||||
public StringAssertions contains(CharSequence... values) {
|
||||
Arrays.stream(values).forEach(value -> {
|
||||
String message = getErrorPrefix() + " does not contain " + value;
|
||||
assertTrue(message, getValue().contains(value));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value does not {@link String#contains contain} the given sub-strings.
|
||||
* @param values the values to match
|
||||
*/
|
||||
public StringAssertions doesNotContain(CharSequence... values) {
|
||||
Arrays.stream(values).forEach(value -> {
|
||||
String message = getErrorPrefix() + " contains " + value + " but shouldn't";
|
||||
assertTrue(message, !getValue().contains(value));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value matches the given regex pattern value.
|
||||
* @param pattern the values to be compiled with {@link Pattern}
|
||||
*/
|
||||
public StringAssertions matches(String pattern) {
|
||||
boolean match = Pattern.compile(pattern).matcher(getValue()).matches();
|
||||
String message = getErrorPrefix() + " with value " + getValue() + " does not match " + pattern;
|
||||
assertTrue(message, match);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||
|
||||
/**
|
||||
* Extension of {@link MultiValueMapEntryAssertions} for String values.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class StringMultiValueMapEntryAssertions extends MultiValueMapEntryAssertions<String> {
|
||||
|
||||
|
||||
public StringMultiValueMapEntryAssertions(ExchangeActions actions, String name,
|
||||
MultiValueMap<String, String> map, String errorMessagePrefix) {
|
||||
|
||||
super(actions, name, map, errorMessagePrefix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The specified value {@link String#contains contains} the given sub-strings.
|
||||
* @param values the values to match
|
||||
*/
|
||||
public ExchangeActions valueContains(CharSequence... values) {
|
||||
String actual = getValue(0);
|
||||
Arrays.stream(values).forEach(value -> {
|
||||
String message = getErrorMessagePrefix() + " does not contain " + value;
|
||||
assertTrue(message, actual.contains(value));
|
||||
});
|
||||
return getExchangeActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* The specified value does not {@link String#contains contain} the given sub-strings.
|
||||
* @param values the values to match
|
||||
*/
|
||||
public ExchangeActions valueDoesNotContain(CharSequence... values) {
|
||||
String actual = getValue(0);
|
||||
Arrays.stream(values).forEach(value -> {
|
||||
String message = getErrorMessagePrefix() + " contains " + value + " but shouldn't";
|
||||
assertTrue(message, !actual.contains(value));
|
||||
});
|
||||
return getExchangeActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* The specified value matches the given regex pattern value.
|
||||
* @param pattern the values to be compiled with {@link Pattern}
|
||||
*/
|
||||
public ExchangeActions valueMatches(String pattern) {
|
||||
String actual = getValue(0);
|
||||
boolean match = Pattern.compile(pattern).matcher(actual).matches();
|
||||
String message = getErrorMessagePrefix() + " with value " + actual + " does not match " + pattern;
|
||||
assertTrue(message, match);
|
||||
return getExchangeActions();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user