Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
<module name="com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.imports.AvoidStaticImportCheck">
<property name="excludes"
value="io.restassured.RestAssured.*, org.assertj.core.api.Assertions.*, org.junit.Assert.*, org.junit.Assume.*, org.junit.internal.matchers.ThrowableMessageMatcher.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.*, org.springframework.boot.configurationprocessor.TestCompiler.*, org.springframework.boot.test.autoconfigure.AutoConfigurationImportedCondition.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.ArgumentMatchers.*, org.mockito.Matchers.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*, org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*, org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*, org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo, org.springframework.test.web.client.ExpectedCount.*, org.springframework.test.web.client.match.MockRestRequestMatchers.*, org.springframework.test.web.client.response.MockRestResponseCreators.*" />
value="io.restassured.RestAssured.*, org.assertj.core.api.Assertions.*, org.junit.Assert.*, org.junit.Assume.*, org.junit.internal.matchers.ThrowableMessageMatcher.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.*, org.springframework.boot.configurationprocessor.TestCompiler.*, org.springframework.boot.test.autoconfigure.AutoConfigurationImportedCondition.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.ArgumentMatchers.*, org.mockito.Matchers.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*, org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*, org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*, org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo, org.springframework.test.web.client.ExpectedCount.*, org.springframework.test.web.client.match.MockRestRequestMatchers.*, org.springframework.test.web.client.response.MockRestResponseCreators.*" />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.*

</module>
<module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck" >
<property name="illegalPkgs" value="com.google.common"/>
Expand Down
5 changes: 5 additions & 0 deletions spring-boot-project/spring-boot-test-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@
<artifactId>spring-restdocs-restassured</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-webtestclient</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
import org.springframework.restdocs.restassured3.RestAssuredRestDocumentation;
import org.springframework.restdocs.restassured3.RestAssuredRestDocumentationConfigurer;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;

/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring REST Docs.
*
* @author Andy Wilkinson
* @author Eddú Meléndez
* @author Roman Zaynetdinov
* @since 1.4.0
*/
@Configuration
Expand Down Expand Up @@ -97,6 +100,7 @@ public RequestSpecification restDocsRestAssuredConfigurer(
configurationCustomizer.customize(configurer);
}
return new RequestSpecBuilder().addFilter(configurer).build();

}

@Bean
Expand All @@ -108,4 +112,33 @@ public RestDocsRestAssuredBuilderCustomizer restAssuredBuilderCustomizer(

}

@Configuration
@ConditionalOnClass(WebTestClientRestDocumentation.class)
@ConditionalOnWebApplication(type = Type.REACTIVE)
static class RestDocsWebTestClientAutoConfiguration {

@Bean
@ConditionalOnMissingBean(WebTestClientRestDocumentationConfigurer.class)
public WebTestClientRestDocumentationConfigurer restDocsWebTestClientConfigurer(
ObjectProvider<RestDocsWebTestClientConfigurationCustomizer> configurationCustomizerProvider,
RestDocumentationContextProvider contextProvider) {
WebTestClientRestDocumentationConfigurer configurer = WebTestClientRestDocumentation
.documentationConfiguration(contextProvider);
RestDocsWebTestClientConfigurationCustomizer configurationCustomizer = configurationCustomizerProvider
.getIfAvailable();
if (configurationCustomizer != null) {
configurationCustomizer.customize(configurer);
}
return configurer;
}

@Bean
@ConfigurationProperties(prefix = "spring.test.restdocs")
public RestDocsWebTestClientBuilderCustomizer restDocumentationConfigurer(
WebTestClientRestDocumentationConfigurer configurer) {
return new RestDocsWebTestClientBuilderCustomizer(configurer);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2012-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.boot.test.autoconfigure.restdocs;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientBuilderCustomizer;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.StringUtils;

/**
* A customizer that configures Spring REST Docs with WebTestClient.
*
* @author Eddú Meléndez
* @author Roman Zaynetdinov
*/
class RestDocsWebTestClientBuilderCustomizer implements InitializingBean, WebTestClientBuilderCustomizer {

private final WebTestClientRestDocumentationConfigurer delegate;

private String uriScheme;

private String uriHost;

private Integer uriPort;

RestDocsWebTestClientBuilderCustomizer(WebTestClientRestDocumentationConfigurer delegate) {
this.delegate = delegate;
}

public String getUriScheme() {
return this.uriScheme;
}

public void setUriScheme(String uriScheme) {
this.uriScheme = uriScheme;
}

public String getUriHost() {
return this.uriHost;
}

public void setUriHost(String uriHost) {
this.uriHost = uriHost;
}

public Integer getUriPort() {
return this.uriPort;
}

public void setUriPort(Integer uriPort) {
this.uriPort = uriPort;
}

@Override
public void afterPropertiesSet() throws Exception {
}

@Override
public void customize(WebTestClient.Builder builder) {
if (StringUtils.hasText(this.uriScheme) && StringUtils.hasText(this.uriHost)) {
String baseUrl = this.uriScheme + "://" + this.uriHost;

if (this.uriPort == 80 && this.uriScheme.equals("http")) {
// Don't add default port
} else if (this.uriPort == 443 && this.uriScheme.equals("https")) {
// Don't add default port
} else if (this.uriPort != null) {
baseUrl += ":" + this.uriPort;
}

builder.baseUrl(baseUrl);
}
builder.filter(this.delegate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2012-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.boot.test.autoconfigure.restdocs;

import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;

/**
* A customizer for {@link WebTestClientRestDocumentationConfigurer}. If a
* {@code RestDocsWebTestClientConfigurationCustomizer} bean is found in the application context
* it will be {@link #customize called} to customize the
* {@code WebTestClientRestDocumentationConfigurer} before it is applied. Intended for use only
* when the attributes on {@link AutoConfigureRestDocs} do not provide sufficient
* customization.
*
* @author Andy Wilkinson
* @author Roman Zaynetdinov
* @since 2.0.0
*/
@FunctionalInterface
public interface RestDocsWebTestClientConfigurationCustomizer {

/**
* Customize the given {@code configurer}.
* @param configurer the configurer
*/
void customize(WebTestClientRestDocumentationConfigurer configurer);

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,21 @@

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.test.autoconfigure.web.servlet.MockMvcBuilderCustomizer;
import org.springframework.boot.web.codec.CodecCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.Builder;
import org.springframework.util.CollectionUtils;
Expand All @@ -49,11 +52,15 @@ public class WebTestClientAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public WebTestClient webTestClient(ApplicationContext applicationContext) {
public WebTestClient webTestClient(ApplicationContext applicationContext,
List<WebTestClientBuilderCustomizer> customizers) {
WebTestClient.Builder builder = WebTestClient
.bindToApplicationContext(applicationContext).configureClient();
customizeWebTestClient(builder, applicationContext);
customizeWebTestClientCodecs(builder, applicationContext);
for (WebTestClientBuilderCustomizer customizer : customizers) {
customizer.customize(builder);
}
return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2012-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.boot.test.autoconfigure.web.reactive;

import org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;

/**
* A customizer for a {@link WebTestClient.Builder}. Any
* {@code WebTestClientBuilderCustomizer} beans found in the application context will be
* {@link #customize called} to customize the auto-configured {@link WebTestClient.Builder}.
*
* @author Andy Wilkinson
* @author Roman Zaynetdinov
* @since 2.0.0
* @see WebTestClientAutoConfiguration
*/
@FunctionalInterface
public interface WebTestClientBuilderCustomizer {

/**
* Customize the given {@code builder}.
* @param builder the builder
*/
void customize(WebTestClient.Builder builder);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2012-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.boot.test.autoconfigure.restdocs;

import java.io.File;

import org.assertj.core.api.Condition;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.FileSystemUtils;


import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;

/**
* Integration tests for {@link RestDocsAutoConfiguration} with WebClientTest.
*
* @author Andy Wilkinson
* @author Roman Zaynetdinov
*/
@RunWith(SpringRunner.class)
@WebFluxTest
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
public class WebTestClientRestDocsAutoConfigurationIntegrationTests {

@Before
public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets"));
}

@Autowired
private WebTestClient webTestClient;

@Test
public void defaultSnippetsAreWritten() throws Exception {
this.webTestClient.get().uri("/").exchange()
.expectBody().consumeWith(document("default-snippets"));
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets");
assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.adoc"))
.has(contentContaining("'https://api.example.com/'"));
assertThat(new File(defaultSnippetsDir, "http-request.adoc"))
.has(contentContaining("api.example.com"));
assertThat(new File(defaultSnippetsDir, "http-response.adoc")).isFile();
}

private Condition<File> contentContaining(String toContain) {
return new ContentContainingCondition(toContain);
}

}