Apply default scheme, host, and port to WebTestClient URIs

Closes gh-461
This commit is contained in:
Andy Wilkinson
2017-11-20 09:40:58 +00:00
parent 17d05f2750
commit 22dd1e75a4
4 changed files with 121 additions and 14 deletions

View File

@@ -55,9 +55,16 @@ specific preprocessor>> is provided for this purpose.
[[configuration-uris-webtestclient]]
==== WebTestClient URI customization
When using WebTestClient, the documented URIs can be customized using the
When using WebTestClient, the default base for URIs documented by Spring REST
Docs is `http://localhost:8080`. This base can be customized using the
{spring-framework-api}/org/springframework/test/web/reactive/server/WebTestClient.Builder.html#baseUrl-java.lang.String-[
`baseUrl(String)` method on `WebTestClient.Builder`].
`baseUrl(String)` method on `WebTestClient.Builder`]:
[source,java,indent=0]
----
include::{examples-dir}/com/example/webtestclient/CustomUriConfiguration.java[tags=custom-uri-configuration]
----
<1> Configure the base of documented URIs to be `https://api.example.com`.

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2014-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 com.example.webtestclient;
import org.junit.Before;
import org.junit.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration;
public class CustomUriConfiguration {
@Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@SuppressWarnings("unused")
private WebTestClient webTestClient;
@Autowired
private WebApplicationContext context;
// tag::custom-uri-configuration[]
@Before
public void setUp() {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
.configureClient()
.baseUrl("https://api.example.com") // <1>
.filter(documentationConfiguration(this.restDocumentation)).build();
}
// end::custom-uri-configuration[]
}

View File

@@ -16,6 +16,8 @@
package org.springframework.restdocs.webtestclient;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -27,6 +29,7 @@ import org.springframework.restdocs.RestDocumentationContext;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.config.RestDocumentationConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
@@ -52,7 +55,8 @@ public class WebTestClientRestDocumentationConfigurer extends
private final RestDocumentationContextProvider contextProvider;
WebTestClientRestDocumentationConfigurer(RestDocumentationContextProvider contextProvider) {
WebTestClientRestDocumentationConfigurer(
RestDocumentationContextProvider contextProvider) {
this.contextProvider = contextProvider;
}
@@ -83,7 +87,23 @@ public class WebTestClientRestDocumentationConfigurer extends
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
String index = request.headers().getFirst(WebTestClient.WEBTESTCLIENT_REQUEST_ID);
configurations.put(index, createConfiguration());
return next.exchange(request);
return next.exchange(applyUriDefaults(request));
}
private ClientRequest applyUriDefaults(ClientRequest request) {
URI requestUri = request.url();
if (!StringUtils.isEmpty(requestUri.getHost())) {
return request;
}
try {
requestUri = new URI("http", requestUri.getUserInfo(), "localhost", 8080,
requestUri.getPath(), requestUri.getQuery(),
requestUri.getFragment());
return ClientRequest.from(request).url(requestUri).build();
}
catch (URISyntaxException ex) {
throw new IllegalStateException(ex);
}
}
}

View File

@@ -16,22 +16,26 @@
package org.springframework.restdocs.webtestclient;
import java.net.URI;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ExchangeFunction;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link WebTestClientRestDocumentationConfigurer}.
@@ -48,17 +52,43 @@ public class WebTestClientRestDocumentationConfigurerTests {
@Test
public void configurationCanBeRetrievedButOnlyOnce() {
ClientRequest request = mock(ClientRequest.class);
HttpHeaders headers = new HttpHeaders();
headers.add(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1");
given(request.headers()).willReturn(headers);
ClientRequest request = ClientRequest.method(HttpMethod.GET, URI.create("/test"))
.header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build();
this.configurer.filter(request, mock(ExchangeFunction.class));
Map<String, Object> configuration = WebTestClientRestDocumentationConfigurer
.retrieveConfiguration(headers);
.retrieveConfiguration(request.headers());
assertThat(configuration, notNullValue());
assertThat(
WebTestClientRestDocumentationConfigurer.retrieveConfiguration(headers),
nullValue());
assertThat(WebTestClientRestDocumentationConfigurer
.retrieveConfiguration(request.headers()), nullValue());
}
@Test
public void requestUriHasDefaultsAppliedWhenItHasNoHost() {
ClientRequest request = ClientRequest
.method(HttpMethod.GET, URI.create("/test?foo=bar#baz"))
.header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build();
ExchangeFunction exchangeFunction = mock(ExchangeFunction.class);
this.configurer.filter(request, exchangeFunction);
ArgumentCaptor<ClientRequest> requestCaptor = ArgumentCaptor
.forClass(ClientRequest.class);
verify(exchangeFunction).exchange(requestCaptor.capture());
assertThat(requestCaptor.getValue().url(),
is(equalTo(URI.create("http://localhost:8080/test?foo=bar#baz"))));
}
@Test
public void requestUriIsNotChangedWhenItHasAHost() {
ClientRequest request = ClientRequest
.method(HttpMethod.GET,
URI.create("https://api.example.com:4567/test?foo=bar#baz"))
.header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build();
ExchangeFunction exchangeFunction = mock(ExchangeFunction.class);
this.configurer.filter(request, exchangeFunction);
ArgumentCaptor<ClientRequest> requestCaptor = ArgumentCaptor
.forClass(ClientRequest.class);
verify(exchangeFunction).exchange(requestCaptor.capture());
assertThat(requestCaptor.getValue().url(),
is(equalTo(URI.create("https://api.example.com:4567/test?foo=bar#baz"))));
}
}