From 896e4db411103c7b747d73a4fec0eed82e1b53ad Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 13 Feb 2017 09:24:36 -0500 Subject: [PATCH] ExchangeActions update Put assertBodyXyz options behind a common assertBody() entry point currently including "isEmpty" and "asMap" but in the future others related to JSON content or XPath for example. Now that ExchangeActions provides method to access the ExchangeInfo it has been removed from constructors of assertion classes that already have ExchangeActions. --- .../web/reactive/server/ExchangeActions.java | 44 ++--------- .../web/reactive/server/ListAssertions.java | 8 +- .../server/LoggingExchangeConsumer.java | 15 ++-- .../web/reactive/server/ObjectAssertions.java | 10 +++ .../server/ResponseBodyAssertions.java | 74 +++++++++++++++++++ .../server/ResponseEntityAssertions.java | 22 +++--- .../server/ResponseStatusAssertions.java | 4 +- .../server/samples/ResponseEntityTests.java | 2 +- 8 files changed, 117 insertions(+), 62 deletions(-) create mode 100644 spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseBodyAssertions.java diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeActions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeActions.java index 2fdf232ce4..6c0da4bc55 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeActions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeActions.java @@ -15,24 +15,16 @@ */ 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; 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; - /** * Entry point for applying assertions and actions on a performed exchange. * @@ -49,21 +41,12 @@ public final class ExchangeActions { } - private ClientResponse getResponse() { - return this.exchangeInfo.getResponse(); - } - - private Duration getResponseTimeout() { - return this.exchangeInfo.getResponseTimeout(); - } - - /** * Assert the status of the response. * @return further options for asserting the status of the response */ public ResponseStatusAssertions assertStatus() { - return new ResponseStatusAssertions(this, this.exchangeInfo); + return new ResponseStatusAssertions(this); } /** @@ -71,7 +54,8 @@ public final class ExchangeActions { * @return further options for asserting headers */ public ResponseHeadersAssertions assertHeaders() { - return new ResponseHeadersAssertions(this, getResponse().headers().asHttpHeaders()); + HttpHeaders headers = this.exchangeInfo.getResponse().headers().asHttpHeaders(); + return new ResponseHeadersAssertions(this, headers); } /** @@ -80,7 +64,7 @@ public final class ExchangeActions { * @return options for asserting the header value(s) */ public ResponseHeaderAssertions assertHeader(String headerName) { - HttpHeaders headers = getResponse().headers().asHttpHeaders(); + HttpHeaders headers = this.exchangeInfo.getResponse().headers().asHttpHeaders(); List values = headers.getOrDefault(headerName, Collections.emptyList()); return new ResponseHeaderAssertions(this, headerName, values); } @@ -88,10 +72,8 @@ public final class ExchangeActions { /** * Assert the response does not have any content. */ - public ExchangeActions assertBodyIsEmpty() { - Flux body = this.exchangeInfo.getResponse().bodyToFlux(ByteBuffer.class); - StepVerifier.create(body).expectComplete().verify(this.exchangeInfo.getResponseTimeout()); - return this; + public ResponseBodyAssertions assertBody() { + return new ResponseBodyAssertions(this); } /** @@ -107,24 +89,14 @@ public final class ExchangeActions { * @return further options for asserting response entities */ public ResponseEntityAssertions assertEntity(ResolvableType entityType) { - return new ResponseEntityAssertions(this, this.exchangeInfo, entityType); - } - - /** - * Assert the response decoded as a Map of the given key and value types. - */ - public MapAssertions assertBodyAsMap(Class keyType, Class valueType) { - ResolvableType type = ResolvableType.forClassWithGenerics(Map.class, keyType, valueType); - Mono> mono = this.exchangeInfo.getResponse().body(toMono(type)); - Map map = mono.block(this.exchangeInfo.getResponseTimeout()); - return new MapAssertions<>(this, map, "Response body map"); + return new ResponseEntityAssertions(this, entityType); } /** * Log debug information about the exchange. */ public LoggingExchangeConsumer log() { - return new LoggingExchangeConsumer(this, this.exchangeInfo); + return new LoggingExchangeConsumer(this); } /** diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ListAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ListAssertions.java index 7748629d47..ea34dc356a 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ListAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ListAssertions.java @@ -22,7 +22,7 @@ import static org.springframework.test.util.AssertionErrors.assertEquals; import static org.springframework.test.util.AssertionErrors.assertTrue; /** - * Assertions on a collection of values. + * Assertions on a List of values. * * @param the type of element values in the collection * @@ -38,7 +38,7 @@ public class ListAssertions extends ObjectAssertions, ListAssertions< /** - * Assert the size of the collection. + * Assert the size of the list. */ public ListAssertions hasSize(int size) { assertEquals(getErrorPrefix() + " count", size, getValue().size()); @@ -46,7 +46,7 @@ public class ListAssertions extends ObjectAssertions, ListAssertions< } /** - * Assert that the collection contains all of the given values. + * Assert that the list contains all of the given values. */ @SuppressWarnings("unchecked") public ListAssertions contains(E... entities) { @@ -58,7 +58,7 @@ public class ListAssertions extends ObjectAssertions, ListAssertions< } /** - * Assert the collection does not contain any of the given values. + * Assert the list does not contain any of the given values. */ @SuppressWarnings("unchecked") public ListAssertions doesNotContain(E... entities) { diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/LoggingExchangeConsumer.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/LoggingExchangeConsumer.java index 65f9e5ef92..00357191c0 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/LoggingExchangeConsumer.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/LoggingExchangeConsumer.java @@ -38,12 +38,9 @@ public class LoggingExchangeConsumer { private final ExchangeActions exchangeActions; - private final ExchangeInfo exchangeInfo; - - public LoggingExchangeConsumer(ExchangeActions exchangeActions, ExchangeInfo exchangeInfo) { + public LoggingExchangeConsumer(ExchangeActions exchangeActions) { this.exchangeActions = exchangeActions; - this.exchangeInfo = exchangeInfo; } @@ -51,7 +48,7 @@ public class LoggingExchangeConsumer { * Log with {@link System#out}. */ public ExchangeActions toConsole() { - System.out.println(this.exchangeInfo.toString()); + System.out.println(getOutput()); return this.exchangeActions; } @@ -67,7 +64,7 @@ public class LoggingExchangeConsumer { */ public ExchangeActions toWriter(Writer writer) { try { - writer.write(this.exchangeInfo.toString()); + writer.write(getOutput()); } catch (IOException ex) { throw new IllegalStateException("Failed to print exchange info", ex); @@ -98,9 +95,13 @@ public class LoggingExchangeConsumer { private ExchangeActions doLog(Predicate logLevelPredicate, BiConsumer logAction) { if (logLevelPredicate.test(logger)) { - logAction.accept(logger, this.exchangeInfo.toString()); + logAction.accept(logger, getOutput()); } return this.exchangeActions; } + private String getOutput() { + return this.exchangeActions.andReturn().toString(); + } + } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ObjectAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ObjectAssertions.java index 2c7a3b7d6e..ee301af050 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ObjectAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ObjectAssertions.java @@ -15,10 +15,12 @@ */ package org.springframework.test.web.reactive.server; +import java.time.Duration; import java.util.function.Consumer; import java.util.function.Supplier; import org.springframework.test.util.AssertionErrors; +import org.springframework.web.reactive.function.client.ClientResponse; import static org.springframework.test.util.AssertionErrors.assertEquals; @@ -113,6 +115,14 @@ public class ObjectAssertions> { return this.exchangeActions; } + protected ClientResponse getResponse() { + return this.exchangeActions.andReturn().getResponse(); + } + + protected Duration getTimeout() { + return this.exchangeActions.andReturn().getResponseTimeout(); + } + protected String getErrorPrefix() { return this.errorPrefix; } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseBodyAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseBodyAssertions.java new file mode 100644 index 0000000000..6b51c7ef9b --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseBodyAssertions.java @@ -0,0 +1,74 @@ +/* + * 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.nio.ByteBuffer; +import java.time.Duration; +import java.util.Map; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import org.springframework.core.ResolvableType; +import org.springframework.web.reactive.function.client.ClientResponse; + +import static org.springframework.web.reactive.function.BodyExtractors.toMono; + +/** + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +public class ResponseBodyAssertions { + + private final ExchangeActions exchangeActions; + + + public ResponseBodyAssertions(ExchangeActions exchangeActions) { + this.exchangeActions = exchangeActions; + } + + + /** + * Assert the response does not have any content. + */ + public ExchangeActions isEmpty() { + Flux body = getResponse().bodyToFlux(ByteBuffer.class); + StepVerifier.create(body).expectComplete().verify(getTimeout()); + return this.exchangeActions; + } + + /** + * Assert the response decoded as a Map of the given key and value types. + */ + public MapAssertions asMap(Class keyType, Class valueType) { + ResolvableType type = ResolvableType.forClassWithGenerics(Map.class, keyType, valueType); + Mono> mono = getResponse().body(toMono(type)); + Map map = mono.block(getTimeout()); + return new MapAssertions<>(this.exchangeActions, map, "Response body map"); + } + + + private ClientResponse getResponse() { + return this.exchangeActions.andReturn().getResponse(); + } + + private Duration getTimeout() { + return this.exchangeActions.andReturn().getResponseTimeout(); + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseEntityAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseEntityAssertions.java index 4a1be70ce8..78363daa9e 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseEntityAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseEntityAssertions.java @@ -36,29 +36,27 @@ import static org.springframework.web.reactive.function.BodyExtractors.toMono; */ public class ResponseEntityAssertions extends ObjectAssertions> { - private final ExchangeInfo exchangeInfo; - private final ResolvableType entityType; - ResponseEntityAssertions(ExchangeActions actions, ExchangeInfo info, ResolvableType entityType) { - super(actions, () -> initEntity(info, entityType), "Response body"); - this.exchangeInfo = info; + ResponseEntityAssertions(ExchangeActions actions, ResolvableType entityType) { + super(actions, () -> initEntity(actions, entityType), "Response body"); this.entityType = entityType; } - private static T initEntity(ExchangeInfo exchangeInfo, ResolvableType entityType) { - Mono mono = exchangeInfo.getResponse().body(toMono(entityType)); - return mono.block(exchangeInfo.getResponseTimeout()); + private static T initEntity(ExchangeActions exchangeActions, ResolvableType entityType) { + ExchangeInfo info = exchangeActions.andReturn(); + Mono mono = info.getResponse().body(toMono(entityType)); + return mono.block(info.getResponseTimeout()); } /** - * Assert the response decoded as a Collection of entities of the given type. + * Assert the response decoded as a List of entities of the given type. */ public ListAssertions list() { - Flux flux = this.exchangeInfo.getResponse().body(toFlux(this.entityType)); - List list = flux.collectList().block(this.exchangeInfo.getResponseTimeout()); + Flux flux = getResponse().body(toFlux(this.entityType)); + List list = flux.collectList().block(getTimeout()); return new ListAssertions(getExchangeActions(), list, "Response entity collection"); } @@ -66,7 +64,7 @@ public class ResponseEntityAssertions extends ObjectAssertions stepVerifier() { - Flux flux = this.exchangeInfo.getResponse().body(toFlux(this.entityType)); + Flux flux = getResponse().body(toFlux(this.entityType)); return StepVerifier.create(flux); } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseStatusAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseStatusAssertions.java index 387392f493..046476c1af 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseStatusAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ResponseStatusAssertions.java @@ -33,9 +33,9 @@ public class ResponseStatusAssertions { private final HttpStatus httpStatus; - ResponseStatusAssertions(ExchangeActions actions, ExchangeInfo info) { + ResponseStatusAssertions(ExchangeActions actions) { this.exchangeActions = actions; - this.httpStatus = info.getResponse().statusCode(); + this.httpStatus = actions.andReturn().getResponse().statusCode(); } diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java index ba7705691a..d56425855c 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java @@ -95,7 +95,7 @@ public class ResponseEntityTests { .exchange(Mono.just(new Person("John")), Person.class) .assertStatus().isCreated() .assertHeader("location").isEqualTo("/persons/John").and() - .assertBodyIsEmpty(); + .assertBody().isEmpty(); }