diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 3d506a0a4900..f2a820ec9221 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -142,6 +142,7 @@
2.3.0
4.1.4
Bismuth-BUILD-SNAPSHOT
+ 3.0.2
1.3.0
1.2.1
2.1.1
@@ -868,6 +869,11 @@
rxjava
${rxjava2.version}
+
+ io.rest-assured
+ rest-assured
+ ${restassured.version}
+
io.searchbox
jest
diff --git a/spring-boot-parent/src/checkstyle/checkstyle.xml b/spring-boot-parent/src/checkstyle/checkstyle.xml
index 5c1d21d34646..20f0028d378d 100644
--- a/spring-boot-parent/src/checkstyle/checkstyle.xml
+++ b/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.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.*, org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.*, 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.match.MockRestRequestMatchers.*, org.springframework.test.web.client.response.MockRestResponseCreators.*" />
diff --git a/spring-boot-test-autoconfigure/pom.xml b/spring-boot-test-autoconfigure/pom.xml
index 51d395e1e6ce..e36ee7c5ed5b 100644
--- a/spring-boot-test-autoconfigure/pom.xml
+++ b/spring-boot-test-autoconfigure/pom.xml
@@ -54,6 +54,11 @@
json-path
true
+
+ io.rest-assured
+ rest-assured
+ true
+
net.sourceforge.htmlunit
htmlunit
@@ -141,6 +146,11 @@
spring-restdocs-mockmvc
true
+
+ org.springframework.restdocs
+ spring-restdocs-restassured
+ true
+
org.springframework.security
spring-security-config
@@ -188,6 +198,11 @@
commons-pool2
test
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+ true
+
org.aspectj
aspectjrt
diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java
index e31c4237512c..c1136f96dddd 100644
--- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java
+++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsAutoConfiguration.java
@@ -16,8 +16,12 @@
package org.springframework.boot.test.autoconfigure.restdocs;
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.specification.RequestSpecification;
+
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
@@ -29,40 +33,77 @@
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
+import org.springframework.restdocs.restassured3.RestAssuredRestDocumentation;
+import org.springframework.restdocs.restassured3.RestAssuredRestDocumentationConfigurer;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring REST Docs.
*
* @author Andy Wilkinson
+ * @author Eddú Meléndez
* @since 1.4.0
*/
@Configuration
-@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties
public class RestDocsAutoConfiguration {
- @Bean
- @ConditionalOnMissingBean(MockMvcRestDocumentationConfigurer.class)
- public MockMvcRestDocumentationConfigurer restDocsMockMvcConfigurer(
- ObjectProvider configurationCustomizerProvider,
- RestDocumentationContextProvider contextProvider) {
- MockMvcRestDocumentationConfigurer configurer = MockMvcRestDocumentation
- .documentationConfiguration(contextProvider);
- RestDocsMockMvcConfigurationCustomizer configurationCustomizer = configurationCustomizerProvider
- .getIfAvailable();
- if (configurationCustomizer != null) {
- configurationCustomizer.customize(configurer);
+ @Configuration
+ @ConditionalOnWebApplication(type = Type.SERVLET)
+ @ConditionalOnClass(MockMvcRestDocumentation.class)
+ static class RestDocsMockMvcAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(MockMvcRestDocumentationConfigurer.class)
+ public MockMvcRestDocumentationConfigurer restDocsMockMvcConfigurer(
+ ObjectProvider configurationCustomizerProvider,
+ RestDocumentationContextProvider contextProvider) {
+ MockMvcRestDocumentationConfigurer configurer = MockMvcRestDocumentation
+ .documentationConfiguration(contextProvider);
+ RestDocsMockMvcConfigurationCustomizer configurationCustomizer = configurationCustomizerProvider
+ .getIfAvailable();
+ if (configurationCustomizer != null) {
+ configurationCustomizer.customize(configurer);
+ }
+ return configurer;
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.test.restdocs")
+ public RestDocsMockMvcBuilderCustomizer restDocumentationConfigurer(
+ MockMvcRestDocumentationConfigurer configurer,
+ ObjectProvider resultHandler) {
+ return new RestDocsMockMvcBuilderCustomizer(configurer,
+ resultHandler.getIfAvailable());
}
- return configurer;
+
}
- @Bean
- @ConfigurationProperties(prefix = "spring.test.restdocs")
- public RestDocsMockMvcBuilderCustomizer restDocumentationConfigurer(
- MockMvcRestDocumentationConfigurer configurer,
- ObjectProvider resultHandler) {
- return new RestDocsMockMvcBuilderCustomizer(configurer,
- resultHandler.getIfAvailable());
+ @Configuration
+ @ConditionalOnClass({ RequestSpecification.class, RestAssuredRestDocumentation.class })
+ static class RestDocsRestAssuredAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(RequestSpecification.class)
+ public RequestSpecification restDocsRestAssuredConfigurer(
+ ObjectProvider configurationCustomizerProvider,
+ RestDocumentationContextProvider contextProvider) {
+ RestAssuredRestDocumentationConfigurer configurer = RestAssuredRestDocumentation
+ .documentationConfiguration(contextProvider);
+ RestDocsRestAssuredConfigurationCustomizer configurationCustomizer = configurationCustomizerProvider.getIfAvailable();
+ if (configurationCustomizer != null) {
+ configurationCustomizer.customize(configurer);
+ }
+ return new RequestSpecBuilder().addFilter(configurer).build();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.test.restdocs")
+ public RestDocsRestAssuredBuilderCustomizer restAssuredBuilderCustomizer(
+ RequestSpecification configurer) {
+ return new RestDocsRestAssuredBuilderCustomizer(configurer);
+ }
+
}
+
}
diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredBuilderCustomizer.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredBuilderCustomizer.java
new file mode 100644
index 000000000000..f5b5335a3312
--- /dev/null
+++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredBuilderCustomizer.java
@@ -0,0 +1,77 @@
+/*
+ * 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 io.restassured.specification.RequestSpecification;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.StringUtils;
+
+/**
+ * A customizer that configures Spring REST Docs with RestAssured.
+ *
+ * @author Eddú Meléndez
+ */
+class RestDocsRestAssuredBuilderCustomizer implements InitializingBean {
+
+ private final RequestSpecification delegate;
+
+ private String uriScheme;
+
+ private String uriHost;
+
+ private Integer uriPort;
+
+ RestDocsRestAssuredBuilderCustomizer(RequestSpecification 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 {
+ if (StringUtils.hasText(this.uriScheme) && StringUtils.hasText(this.uriHost)) {
+ this.delegate.baseUri(this.uriScheme + "://" + this.uriHost);
+ }
+ if (this.uriPort != null) {
+ this.delegate.port(this.uriPort);
+ }
+ }
+
+}
diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredConfigurationCustomizer.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredConfigurationCustomizer.java
new file mode 100644
index 000000000000..01aaba49df5d
--- /dev/null
+++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredConfigurationCustomizer.java
@@ -0,0 +1,41 @@
+/*
+ * 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.restassured3.RestAssuredRestDocumentationConfigurer;
+
+/**
+ * A customizer for {@link RestAssuredRestDocumentationConfigurer}. If a
+ * {@code RestDocsRestAssuredConfigurationCustomizer} bean is found in the application
+ * context it will be {@link #customize called} to customize the
+ * {@code RestAssuredRestDocumentationConfigurer} before it is applied. Intended for use
+ * only when the attributes on {@link AutoConfigureRestDocs} do not provide sufficient
+ * customization.
+ *
+ * @author Eddú Meléndez
+ * @since 2.0.0
+ */
+@FunctionalInterface
+public interface RestDocsRestAssuredConfigurationCustomizer {
+
+ /**
+ * Customize the given {@code configurer}.
+ * @param configurer the configurer
+ */
+ void customize(RestAssuredRestDocumentationConfigurer configurer);
+
+}
diff --git a/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories
index 0d335481a554..ce87c81d4e0c 100644
--- a/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -145,4 +145,4 @@ org.springframework.test.context.TestExecutionListener=\
org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener,\
org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener,\
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener,\
-org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener
\ No newline at end of file
+org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener
diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredAutoConfigurationAdvancedConfigurationIntegrationTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredAutoConfigurationAdvancedConfigurationIntegrationTests.java
new file mode 100644
index 000000000000..86e8db83889b
--- /dev/null
+++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredAutoConfigurationAdvancedConfigurationIntegrationTests.java
@@ -0,0 +1,95 @@
+/*
+ * 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 io.restassured.specification.RequestSpecification;
+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.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.restdocs.restassured3.RestAssuredRestDocumentationConfigurer;
+import org.springframework.restdocs.templates.TemplateFormats;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.util.FileSystemUtils;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;
+import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris;
+
+/**
+ * Tests for {@link AutoConfigureRestDocs}.
+ *
+ * @author Eddú Meléndez
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@AutoConfigureRestDocs
+public class RestAssuredAutoConfigurationAdvancedConfigurationIntegrationTests {
+
+ @LocalServerPort
+ private int port;
+
+ @Before
+ public void deleteSnippets() {
+ FileSystemUtils.deleteRecursively(new File("target/generated-snippets"));
+ }
+
+ @Autowired
+ private RequestSpecification documentationSpec;
+
+ @Test
+ public void snippetGeneration() throws Exception {
+ given(this.documentationSpec)
+ .filter(document("default-snippets", preprocessRequest(modifyUris()
+ .scheme("https").host("api.example.com").removePort()))).when()
+ .port(this.port).get("/").then().assertThat().statusCode(is(200));
+ File defaultSnippetsDir = new File("target/generated-snippets/default-snippets");
+ assertThat(defaultSnippetsDir).exists();
+ assertThat(new File(defaultSnippetsDir, "curl-request.md")).has(
+ contentContaining("'https://api.example.com/'"));
+ assertThat(new File(defaultSnippetsDir, "http-request.md")).has(
+ contentContaining("api.example.com"));
+ assertThat(new File(defaultSnippetsDir, "http-response.md")).isFile();
+ }
+
+ private Condition contentContaining(String toContain) {
+ return new ContentContainingCondition(toContain);
+ }
+
+ @TestConfiguration
+ public static class CustomizationConfiguration implements
+ RestDocsRestAssuredConfigurationCustomizer {
+
+ @Override
+ public void customize(RestAssuredRestDocumentationConfigurer configurer) {
+ configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
+ }
+
+ }
+
+}
diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredAutoConfigurationIntegrationTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredAutoConfigurationIntegrationTests.java
new file mode 100644
index 000000000000..adc73336f442
--- /dev/null
+++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredAutoConfigurationIntegrationTests.java
@@ -0,0 +1,81 @@
+/*
+ * 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 io.restassured.specification.RequestSpecification;
+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.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.util.FileSystemUtils;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;
+import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris;
+
+/**
+ * Tests for {@link RestDocsAutoConfiguration}
+ *
+ * @author Eddú Meléndez
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@AutoConfigureRestDocs
+public class RestAssuredAutoConfigurationIntegrationTests {
+
+ @LocalServerPort
+ private int port;
+
+ @Before
+ public void deleteSnippets() {
+ FileSystemUtils.deleteRecursively(new File("target/generated-snippets"));
+ }
+
+ @Autowired
+ private RequestSpecification documentationSpec;
+
+ @Test
+ public void defaultSnippetsAreWritten() throws Exception {
+ given(this.documentationSpec)
+ .filter(document("default-snippets", preprocessRequest(modifyUris()
+ .scheme("https").host("api.example.com").removePort()))).when()
+ .port(this.port).get("/").then().assertThat().statusCode(is(200));
+ 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);
+ }
+
+}
diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java
index eef3c6095fbd..ce7d6356162c 100644
--- a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java
+++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java
@@ -17,13 +17,14 @@
package org.springframework.boot.test.autoconfigure.restdocs;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
/**
* Test application used with {@link AutoConfigureRestDocs} tests.
*
* @author Andy Wilkinson
*/
-@SpringBootApplication
+@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class RestDocsTestApplication {
}