Skip to content

Commit adf0d61

Browse files
committed
Merge pull request #10969 from Roman Zaynetdinov
* gh-10969: Polish "Add auto-configuration for using REST Docs with WebTestClient" Add auto-configuration for using REST Docs with WebTestClient
2 parents 16c52bc + 964939d commit adf0d61

File tree

6 files changed

+242
-1
lines changed

6 files changed

+242
-1
lines changed

spring-boot-project/spring-boot-parent/src/checkstyle/checkstyle.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
<module name="com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck" />
7171
<module name="com.puppycrawl.tools.checkstyle.checks.imports.AvoidStaticImportCheck">
7272
<property name="excludes"
73-
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.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.*" />
73+
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.*" />
7474
</module>
7575
<module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck" >
7676
<property name="illegalPkgs" value="sun, org.apache.commons.(?!codec|compress|dbcp2|lang|lang3|logging|pool2).*, com.google.common, org.flywaydb.core.internal"/>

spring-boot-project/spring-boot-test-autoconfigure/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@
152152
<artifactId>spring-restdocs-restassured</artifactId>
153153
<optional>true</optional>
154154
</dependency>
155+
<dependency>
156+
<groupId>org.springframework.restdocs</groupId>
157+
<artifactId>spring-restdocs-webtestclient</artifactId>
158+
<optional>true</optional>
159+
</dependency>
155160
<dependency>
156161
<groupId>org.springframework.security</groupId>
157162
<artifactId>spring-security-config</artifactId>

spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@
3535
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
3636
import org.springframework.restdocs.restassured3.RestAssuredRestDocumentation;
3737
import org.springframework.restdocs.restassured3.RestAssuredRestDocumentationConfigurer;
38+
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation;
39+
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
3840

3941
/**
4042
* {@link EnableAutoConfiguration Auto-configuration} for Spring REST Docs.
4143
*
4244
* @author Andy Wilkinson
4345
* @author Eddú Meléndez
46+
* @author Roman Zaynetdinov
4447
* @since 1.4.0
4548
*/
4649
@Configuration
@@ -108,4 +111,33 @@ public RestDocsRestAssuredBuilderCustomizer restAssuredBuilderCustomizer(
108111

109112
}
110113

114+
@Configuration
115+
@ConditionalOnClass(WebTestClientRestDocumentation.class)
116+
@ConditionalOnWebApplication(type = Type.REACTIVE)
117+
static class RestDocsWebTestClientAutoConfiguration {
118+
119+
@Bean
120+
@ConditionalOnMissingBean(WebTestClientRestDocumentationConfigurer.class)
121+
public WebTestClientRestDocumentationConfigurer restDocsWebTestClientConfigurer(
122+
ObjectProvider<RestDocsWebTestClientConfigurationCustomizer> configurationCustomizerProvider,
123+
RestDocumentationContextProvider contextProvider) {
124+
WebTestClientRestDocumentationConfigurer configurer = WebTestClientRestDocumentation
125+
.documentationConfiguration(contextProvider);
126+
RestDocsWebTestClientConfigurationCustomizer configurationCustomizer = configurationCustomizerProvider
127+
.getIfAvailable();
128+
if (configurationCustomizer != null) {
129+
configurationCustomizer.customize(configurer);
130+
}
131+
return configurer;
132+
}
133+
134+
@Bean
135+
@ConfigurationProperties(prefix = "spring.test.restdocs")
136+
public RestDocsWebTestClientBuilderCustomizer restDocumentationConfigurer(
137+
WebTestClientRestDocumentationConfigurer configurer) {
138+
return new RestDocsWebTestClientBuilderCustomizer(configurer);
139+
}
140+
141+
}
142+
111143
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.autoconfigure.restdocs;
18+
19+
import org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientBuilderCustomizer;
20+
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
21+
import org.springframework.test.web.reactive.server.WebTestClient;
22+
import org.springframework.util.StringUtils;
23+
24+
/**
25+
* A {@WebTestClientBuilderCustomizer} that configures Spring REST Docs.
26+
*
27+
* @author Roman Zaynetdinov
28+
* @author Andy Wilkinson
29+
*/
30+
class RestDocsWebTestClientBuilderCustomizer implements WebTestClientBuilderCustomizer {
31+
32+
private final WebTestClientRestDocumentationConfigurer delegate;
33+
34+
private String uriScheme;
35+
36+
private String uriHost;
37+
38+
private Integer uriPort;
39+
40+
RestDocsWebTestClientBuilderCustomizer(
41+
WebTestClientRestDocumentationConfigurer delegate) {
42+
this.delegate = delegate;
43+
}
44+
45+
public String getUriScheme() {
46+
return this.uriScheme;
47+
}
48+
49+
public void setUriScheme(String uriScheme) {
50+
this.uriScheme = uriScheme;
51+
}
52+
53+
public String getUriHost() {
54+
return this.uriHost;
55+
}
56+
57+
public void setUriHost(String uriHost) {
58+
this.uriHost = uriHost;
59+
}
60+
61+
public Integer getUriPort() {
62+
return this.uriPort;
63+
}
64+
65+
public void setUriPort(Integer uriPort) {
66+
this.uriPort = uriPort;
67+
}
68+
69+
@Override
70+
public void customize(WebTestClient.Builder builder) {
71+
customizeBaseUrl(builder);
72+
builder.filter(this.delegate);
73+
}
74+
75+
private void customizeBaseUrl(WebTestClient.Builder builder) {
76+
String scheme = StringUtils.hasText(this.uriScheme) ? this.uriScheme : "http";
77+
String host = StringUtils.hasText(this.uriHost) ? this.uriHost : "localhost";
78+
String baseUrl = scheme + "://" + host;
79+
if (!isStandardPort()) {
80+
baseUrl += ":" + this.uriPort;
81+
}
82+
builder.baseUrl(baseUrl);
83+
}
84+
85+
private boolean isStandardPort() {
86+
if (this.uriPort == null) {
87+
return true;
88+
}
89+
return this.uriScheme.equals("http") && this.uriPort == 80
90+
|| this.uriScheme.equals("https") && this.uriPort.equals(443);
91+
}
92+
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.autoconfigure.restdocs;
18+
19+
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
20+
21+
/**
22+
* A customizer for {@link WebTestClientRestDocumentationConfigurer}. If a
23+
* {@code RestDocsWebTestClientConfigurationCustomizer} bean is found in the application
24+
* context it will be {@link #customize called} to customize the
25+
* {@code WebTestClientRestDocumentationConfigurer} before it is applied. Intended for use
26+
* only when the attributes on {@link AutoConfigureRestDocs} do not provide sufficient
27+
* customization.
28+
*
29+
* @author Roman Zaynetdinov
30+
* @since 2.0.0
31+
*/
32+
@FunctionalInterface
33+
public interface RestDocsWebTestClientConfigurationCustomizer {
34+
35+
/**
36+
* Customize the given {@code configurer}.
37+
* @param configurer the configurer
38+
*/
39+
void customize(WebTestClientRestDocumentationConfigurer configurer);
40+
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.autoconfigure.restdocs;
18+
19+
import java.io.File;
20+
21+
import org.assertj.core.api.Condition;
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
26+
import org.springframework.beans.factory.annotation.Autowired;
27+
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
28+
import org.springframework.test.context.junit4.SpringRunner;
29+
import org.springframework.test.web.reactive.server.WebTestClient;
30+
import org.springframework.util.FileSystemUtils;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
34+
35+
/**
36+
* Integration tests for {@link RestDocsAutoConfiguration} with {@link WebTestClient}.
37+
*
38+
* @author Roman Zaynetdinov
39+
*/
40+
@RunWith(SpringRunner.class)
41+
@WebFluxTest
42+
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
43+
public class WebTestClientRestDocsAutoConfigurationIntegrationTests {
44+
45+
@Before
46+
public void deleteSnippets() {
47+
FileSystemUtils.deleteRecursively(new File("target/generated-snippets"));
48+
}
49+
50+
@Autowired
51+
private WebTestClient webTestClient;
52+
53+
@Test
54+
public void defaultSnippetsAreWritten() throws Exception {
55+
this.webTestClient.get().uri("/").exchange().expectBody()
56+
.consumeWith(document("default-snippets"));
57+
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets");
58+
assertThat(defaultSnippetsDir).exists();
59+
assertThat(new File(defaultSnippetsDir, "curl-request.adoc"))
60+
.has(contentContaining("'https://api.example.com/'"));
61+
assertThat(new File(defaultSnippetsDir, "http-request.adoc"))
62+
.has(contentContaining("api.example.com"));
63+
assertThat(new File(defaultSnippetsDir, "http-response.adoc")).isFile();
64+
}
65+
66+
private Condition<File> contentContaining(String toContain) {
67+
return new ContentContainingCondition(toContain);
68+
}
69+
70+
}

0 commit comments

Comments
 (0)