diff --git a/build.gradle b/build.gradle index 5feb98d8532..51695667176 100644 --- a/build.gradle +++ b/build.gradle @@ -1016,6 +1016,8 @@ project("spring-test") { } optional("org.skyscreamer:jsonassert:1.3.0") optional("com.jayway.jsonpath:json-path:2.2.0") + optional("org.reactivestreams:reactive-streams:${reactivestreamsVersion}") + optional("io.projectreactor:reactor-core:${reactorCoreVersion}") testCompile(project(":spring-context-support")) testCompile(project(":spring-oxm")) testCompile("javax.mail:javax.mail-api:${javamailVersion}") diff --git a/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java new file mode 100644 index 00000000000..a7f847e45ba --- /dev/null +++ b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2002-2016 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.mock.http.server.reactive; + +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; + +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.HttpCookie; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * Mock implementation of {@link ServerHttpRequest}. + * @author Rossen Stoyanchev + */ +public class MockServerHttpRequest implements ServerHttpRequest { + + private HttpMethod httpMethod; + + private URI url; + + private final MultiValueMap queryParams = new LinkedMultiValueMap<>(); + + private final HttpHeaders headers = new HttpHeaders(); + + private final MultiValueMap cookies = new LinkedMultiValueMap<>(); + + private Flux body = Flux.empty(); + + + /** + * Create a new instance where the HTTP method and/or URL can be set later + * via {@link #setHttpMethod(HttpMethod)} and {@link #setUri(URI)}. + */ + public MockServerHttpRequest() { + } + + /** + * Convenience alternative to {@link #MockServerHttpRequest(HttpMethod, URI)} + * that accepts a String URL. + */ + public MockServerHttpRequest(HttpMethod httpMethod, String url) { + this(httpMethod, (url != null ? URI.create(url) : null)); + } + + /** + * Create a new instance with the given HTTP method and URL. + */ + public MockServerHttpRequest(HttpMethod httpMethod, URI url) { + this.httpMethod = httpMethod; + this.url = url; + } + + + public void setHttpMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + } + + @Override + public HttpMethod getMethod() { + return this.httpMethod; + } + + public MockServerHttpRequest setUri(String url) { + this.url = URI.create(url); + return this; + } + + public MockServerHttpRequest setUri(URI uri) { + this.url = uri; + return this; + } + + @Override + public URI getURI() { + return this.url; + } + + public MockServerHttpRequest addHeader(String name, String value) { + getHeaders().add(name, value); + return this; + } + + public MockServerHttpRequest setHeader(String name, String value) { + getHeaders().set(name, value); + return this; + } + + @Override + public HttpHeaders getHeaders() { + return this.headers; + } + + @Override + public MultiValueMap getQueryParams() { + return this.queryParams; + } + + @Override + public MultiValueMap getCookies() { + return this.cookies; + } + + public MockServerHttpRequest setBody(Publisher body) { + this.body = Flux.from(body); + return this; + } + + public MockServerHttpRequest setBody(String body) { + DataBuffer buffer = toDataBuffer(body, StandardCharsets.UTF_8); + this.body = Flux.just(buffer); + return this; + } + + public MockServerHttpRequest setBody(String body, Charset charset) { + DataBuffer buffer = toDataBuffer(body, charset); + this.body = Flux.just(buffer); + return this; + } + + private DataBuffer toDataBuffer(String body, Charset charset) { + byte[] bytes = body.getBytes(charset); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + return new DefaultDataBufferFactory().wrap(byteBuffer); + } + + @Override + public Flux getBody() { + return this.body; + } + +} diff --git a/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpResponse.java b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpResponse.java new file mode 100644 index 00000000000..b6df9e6d0c3 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpResponse.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2016 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.mock.http.server.reactive; + +import java.util.function.Supplier; + +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseCookie; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * Mock implementation of {@link ServerHttpResponse}. + * @author Rossen Stoyanchev + */ +public class MockServerHttpResponse implements ServerHttpResponse { + + private HttpStatus status; + + private final HttpHeaders headers = new HttpHeaders(); + + private final MultiValueMap cookies = new LinkedMultiValueMap<>(); + + private Publisher body; + + private Publisher> bodyWithFlushes; + + private DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); + + + @Override + public boolean setStatusCode(HttpStatus status) { + this.status = status; + return true; + } + + public HttpStatus getStatusCode() { + return this.status; + } + + @Override + public HttpHeaders getHeaders() { + return this.headers; + } + + @Override + public MultiValueMap getCookies() { + return this.cookies; + } + + public Publisher getBody() { + return this.body; + } + + public Publisher> getBodyWithFlush() { + return this.bodyWithFlushes; + } + + @Override + public Mono writeWith(Publisher body) { + this.body = body; + return Flux.from(this.body).then(); + } + + @Override + public Mono writeAndFlushWith(Publisher> body) { + this.bodyWithFlushes = body; + return Flux.from(this.bodyWithFlushes).then(); + } + + @Override + public void beforeCommit(Supplier> action) { + } + + @Override + public Mono setComplete() { + return Mono.empty(); + } + + @Override + public DataBufferFactory bufferFactory() { + return this.bufferFactory; + } + +} diff --git a/spring-test/src/main/java/org/springframework/mock/http/server/reactive/package-info.java b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/package-info.java new file mode 100644 index 00000000000..5336e97cedd --- /dev/null +++ b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/package-info.java @@ -0,0 +1,4 @@ +/** + * Mock implementations of reactive HTTP server contracts. + */ +package org.springframework.mock.http.server.reactive; diff --git a/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java b/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java index 73794c4da60..228a0e9c757 100644 --- a/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java +++ b/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java @@ -32,7 +32,6 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; - /** * Mock implementation of {@link ServerHttpRequest}. * @author Rossen Stoyanchev