From ab7c47d340341aea690ce0ce2e32f564e494cabd Mon Sep 17 00:00:00 2001 From: Roman Zaynetdinov Date: Thu, 9 Nov 2017 19:24:18 +0200 Subject: [PATCH 1/2] Add auto-configuration for using REST Docs with WebTestClient See gh-10969 --- .../src/checkstyle/checkstyle.xml | 2 +- .../spring-boot-test-autoconfigure/pom.xml | 5 ++ .../restdocs/RestDocsAutoConfiguration.java | 32 +++++++ ...estDocsWebTestClientBuilderCustomizer.java | 90 +++++++++++++++++++ ...sWebTestClientConfigurationCustomizer.java | 42 +++++++++ ...DocsAutoConfigurationIntegrationTests.java | 72 +++++++++++++++ 6 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java diff --git a/spring-boot-project/spring-boot-parent/src/checkstyle/checkstyle.xml b/spring-boot-project/spring-boot-parent/src/checkstyle/checkstyle.xml index 0f8c41e0875..60bb719b4e3 100644 --- a/spring-boot-project/spring-boot-parent/src/checkstyle/checkstyle.xml +++ b/spring-boot-project/spring-boot-parent/src/checkstyle/checkstyle.xml @@ -70,7 +70,7 @@ + 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.payload.PayloadDocumentation.*, org.springframework.restdocs.request.RequestDocumentation.*, org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.*, org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.*, 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.*" /> diff --git a/spring-boot-project/spring-boot-test-autoconfigure/pom.xml b/spring-boot-project/spring-boot-test-autoconfigure/pom.xml index d8c8c340e37..63e13a21fb3 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/pom.xml +++ b/spring-boot-project/spring-boot-test-autoconfigure/pom.xml @@ -152,6 +152,11 @@ spring-restdocs-restassured true + + org.springframework.restdocs + spring-restdocs-webtestclient + true + org.springframework.security spring-security-config diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java index 7941b6cb1e7..be6c39cf7b0 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java @@ -35,12 +35,15 @@ import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer; 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 @@ -108,4 +111,33 @@ public class RestDocsAutoConfiguration { } + @Configuration + @ConditionalOnClass(WebTestClientRestDocumentation.class) + @ConditionalOnWebApplication(type = Type.REACTIVE) + static class RestDocsWebTestClientAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(WebTestClientRestDocumentationConfigurer.class) + public WebTestClientRestDocumentationConfigurer restDocsWebTestClientConfigurer( + ObjectProvider 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); + } + + } + } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java new file mode 100644 index 00000000000..22e72b342b7 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java @@ -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); + } +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java new file mode 100644 index 00000000000..cebff084c7c --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java @@ -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); + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java new file mode 100644 index 00000000000..d0558fe566c --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java @@ -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 contentContaining(String toContain) { + return new ContentContainingCondition(toContain); + } + +} From 964939d3a9b5671a37b394677188ec4c6cf0e335 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 9 Jan 2018 11:53:12 +0000 Subject: [PATCH 2/2] Polish "Add auto-configuration for using REST Docs with WebTestClient" Closes gh-10696 --- ...estDocsWebTestClientBuilderCustomizer.java | 49 ++++++++++--------- ...sWebTestClientConfigurationCustomizer.java | 11 ++--- ...DocsAutoConfigurationIntegrationTests.java | 10 ++-- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java index 22e72b342b7..e7206a3a308 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientBuilderCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -16,19 +16,18 @@ 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. + * A {@WebTestClientBuilderCustomizer} that configures Spring REST Docs. * - * @author Eddú Meléndez * @author Roman Zaynetdinov + * @author Andy Wilkinson */ -class RestDocsWebTestClientBuilderCustomizer implements InitializingBean, WebTestClientBuilderCustomizer { +class RestDocsWebTestClientBuilderCustomizer implements WebTestClientBuilderCustomizer { private final WebTestClientRestDocumentationConfigurer delegate; @@ -38,7 +37,8 @@ class RestDocsWebTestClientBuilderCustomizer implements InitializingBean, WebTes private Integer uriPort; - RestDocsWebTestClientBuilderCustomizer(WebTestClientRestDocumentationConfigurer delegate) { + RestDocsWebTestClientBuilderCustomizer( + WebTestClientRestDocumentationConfigurer delegate) { this.delegate = delegate; } @@ -66,25 +66,28 @@ class RestDocsWebTestClientBuilderCustomizer implements InitializingBean, WebTes 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); - } + customizeBaseUrl(builder); builder.filter(this.delegate); } + + private void customizeBaseUrl(WebTestClient.Builder builder) { + String scheme = StringUtils.hasText(this.uriScheme) ? this.uriScheme : "http"; + String host = StringUtils.hasText(this.uriHost) ? this.uriHost : "localhost"; + String baseUrl = scheme + "://" + host; + if (!isStandardPort()) { + baseUrl += ":" + this.uriPort; + } + builder.baseUrl(baseUrl); + } + + private boolean isStandardPort() { + if (this.uriPort == null) { + return true; + } + return this.uriScheme.equals("http") && this.uriPort == 80 + || this.uriScheme.equals("https") && this.uriPort.equals(443); + } + } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java index cebff084c7c..0a7745a7b52 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsWebTestClientConfigurationCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -20,13 +20,12 @@ import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation /** * 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 + * {@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 */ diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java index d0558fe566c..31f93934eef 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/WebTestClientRestDocsAutoConfigurationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -29,14 +29,12 @@ 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. + * Integration tests for {@link RestDocsAutoConfiguration} with {@link WebTestClient}. * - * @author Andy Wilkinson * @author Roman Zaynetdinov */ @RunWith(SpringRunner.class) @@ -54,8 +52,8 @@ public class WebTestClientRestDocsAutoConfigurationIntegrationTests { @Test public void defaultSnippetsAreWritten() throws Exception { - this.webTestClient.get().uri("/").exchange() - .expectBody().consumeWith(document("default-snippets")); + 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"))