diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f0ade3dbf5c..1b1cf1a42d2 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1107,6 +1107,19 @@ bom { ] } } + library("REST Assured", "4.5.0") { + group("io.rest-assured") { + modules = [ + "json-path", + "json-schema-validator", + "rest-assured", + "scala-support", + "spring-mock-mvc", + "spring-web-test-client", + "xml-path" + ] + } + } library("RSocket", "1.1.1") { group("io.rsocket") { imports = [ diff --git a/spring-boot-project/spring-boot-docs/build.gradle b/spring-boot-project/spring-boot-docs/build.gradle index c75683d2a0a..90205f1ecf5 100644 --- a/spring-boot-project/spring-boot-docs/build.gradle +++ b/spring-boot-project/spring-boot-docs/build.gradle @@ -143,6 +143,11 @@ dependencies { implementation("org.springframework.restdocs:spring-restdocs-mockmvc") { exclude group: "javax.servlet", module: "javax.servlet-api" } + implementation("org.springframework.restdocs:spring-restdocs-restassured") { + exclude group: "commons-logging", module: "commons-logging" + exclude group: "javax.activation", module: "activation" + exclude group: "javax.xml.bind", module: "jaxb-api" + } implementation("org.springframework.restdocs:spring-restdocs-webtestclient") implementation("org.springframework.security:spring-security-config") implementation("org.springframework.security:spring-security-oauth2-client") diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties index 93b20fca627..ce9c3e8d012 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties @@ -347,6 +347,7 @@ boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-clien boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs=features.testing.spring-boot-applications.autoconfigured-spring-restdocs boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs-mock-mvc=features.testing.spring-boot-applications.autoconfigured-spring-restdocs.with-mock-mvc boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs-web-test-client=features.testing.spring-boot-applications.autoconfigured-spring-restdocs.with-web-test-client +boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs-rest-assured=features.testing.spring-boot-applications.autoconfigured-spring-restdocs.with-rest-assured boot-features-testing-spring-boot-applications-testing-autoconfigured-webservices=features.testing.spring-boot-applications.autoconfigured-webservices boot-features-testing-spring-boot-applications-testing-auto-configured-additional-auto-config=features.testing.spring-boot-applications.additional-autoconfiguration-and-slicing boot-features-testing-spring-boot-applications-testing-user-configuration=features.testing.spring-boot-applications.user-configuration-and-slicing diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index 4d8e5636806..c8e64b8ac08 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -701,7 +701,7 @@ include::{docs-java}/features/testing/springbootapplications/autoconfiguredrestc [[features.testing.spring-boot-applications.autoconfigured-spring-restdocs]] ==== Auto-configured Spring REST Docs Tests -You can use the `@AutoConfigureRestDocs` annotation to use {spring-restdocs}[Spring REST Docs] in your tests with Mock MVC or WebTestClient. +You can use the `@AutoConfigureRestDocs` annotation to use {spring-restdocs}[Spring REST Docs] in your tests with Mock MVC, REST Assured, or WebTestClient. It removes the need for the JUnit extension in Spring REST Docs. `@AutoConfigureRestDocs` can be used to override the default output directory (`target/generated-snippets` if you are using Maven or `build/generated-snippets` if you are using Gradle). @@ -764,6 +764,25 @@ include::{docs-java}/features/testing/springbootapplications/autoconfiguredsprin +[[features.testing.spring-boot-applications.autoconfigured-spring-restdocs.with-rest-assured]] +===== Auto-configured Spring REST Docs Tests with REST Assured +`@AutoConfigureRestDocs` makes a `RequestSpecification` bean, preconfigured to use Spring REST Docs, available to your tests. +You can inject it by using `@Autowired` and use it in your tests as you normally would when using REST Assured and Spring REST Docs, as shown in the following example: + +[source,java,indent=0,subs="verbatim"] +---- +include::{docs-java}/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyUserDocumentationTests.java[] +---- + +If you require more control over Spring REST Docs configuration than offered by the attributes of `@AutoConfigureRestDocs`, a `RestDocsRestAssuredConfigurationCustomizer` bean can be used, as shown in the following example: + +[source,java,indent=0,subs="verbatim"] +---- +include::{docs-java}/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyRestDocsConfiguration.java[] +---- + + + [[features.testing.spring-boot-applications.autoconfigured-webservices]] ==== Auto-configured Spring Web Services Tests diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyRestDocsConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyRestDocsConfiguration.java new file mode 100644 index 00000000000..699b5e3747f --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyRestDocsConfiguration.java @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.docs.features.testing.springbootapplications.autoconfiguredspringrestdocs.withrestassured; + +import org.springframework.boot.test.autoconfigure.restdocs.RestDocsRestAssuredConfigurationCustomizer; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer; +import org.springframework.restdocs.templates.TemplateFormats; + +@TestConfiguration(proxyBeanMethods = false) +public class MyRestDocsConfiguration implements RestDocsRestAssuredConfigurationCustomizer { + + @Override + public void customize(RestAssuredRestDocumentationConfigurer configurer) { + configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyUserDocumentationTests.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyUserDocumentationTests.java new file mode 100644 index 00000000000..9799fbfa4b9 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/springbootapplications/autoconfiguredspringrestdocs/withrestassured/MyUserDocumentationTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.docs.features.testing.springbootapplications.autoconfiguredspringrestdocs.withrestassured; + +import io.restassured.specification.RequestSpecification; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; +import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@AutoConfigureRestDocs +class MyUserDocumentationTests { + + @Test + void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) { + // @formatter:off + given(documentationSpec) + .filter(document("list-users")) + .when() + .port(port) + .get("/") + .then().assertThat() + .statusCode(is(200)); + // @formatter:on + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle index 981d70eb6bb..f7f620e756b 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle @@ -20,6 +20,11 @@ dependencies { optional("com.google.code.gson:gson") optional("com.jayway.jsonpath:json-path") optional("com.sun.xml.messaging.saaj:saaj-impl") + optional("io.rest-assured:rest-assured") { + exclude group: "commons-logging", module: "commons-logging" + exclude group: "javax.activation", module: "activation" + exclude group: "javax.xml.bind", module: "jaxb-api" + } optional("net.sourceforge.htmlunit:htmlunit") { exclude group: "commons-logging", module: "commons-logging" } @@ -47,6 +52,11 @@ dependencies { optional("org.springframework.restdocs:spring-restdocs-mockmvc") { exclude group: "javax.servlet", module: "javax.servlet-api" } + optional("org.springframework.restdocs:spring-restdocs-restassured") { + exclude group: "commons-logging", module: "commons-logging" + exclude group: "javax.activation", module: "activation" + exclude group: "javax.xml.bind", module: "jaxb-api" + } optional("org.springframework.restdocs:spring-restdocs-webtestclient") optional("org.springframework.security:spring-security-config") optional("org.springframework.security:spring-security-test") diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java index 92947582db1..905af869926 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2020 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. @@ -23,6 +23,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import io.restassured.RestAssured; + import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.test.autoconfigure.properties.PropertyMapping; import org.springframework.context.annotation.Import; @@ -33,19 +35,22 @@ import org.springframework.test.web.servlet.MockMvc; /** * Annotation that can be applied to a test class to enable and configure * auto-configuration of Spring REST Docs. The auto-configuration sets up - * {@link MockMvc}-based testing of a servlet web application or - * {@link WebTestClient}-based testing of a reactive web application. + * {@link MockMvc}-based testing of a servlet web application, {@link WebTestClient}-based + * testing of a reactive web application, or {@link RestAssured}-based testing of any web + * application over HTTP. *

* Allows configuration of the output directory and the host, scheme, and port of * generated URIs. When further configuration is required a - * {@link RestDocsMockMvcConfigurationCustomizer} or - * {@link RestDocsWebTestClientConfigurationCustomizer} bean can be used. + * {@link RestDocsMockMvcConfigurationCustomizer}, + * {@link RestDocsWebTestClientConfigurationCustomizer}, or + * {@link RestDocsRestAssuredConfigurationCustomizer} bean can be used. * * @author Andy Wilkinson * @since 1.4.0 * @see RestDocsAutoConfiguration * @see RestDocsMockMvcConfigurationCustomizer * @see RestDocsWebTestClientConfigurationCustomizer + * @see RestDocsRestAssuredConfigurationCustomizer */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) 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 387132c7676..42459c52103 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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,6 +16,9 @@ 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; @@ -29,6 +32,8 @@ import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.restassured.RestAssuredRestDocumentation; +import org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer; import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation; import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer; @@ -71,6 +76,31 @@ public class RestDocsAutoConfiguration { } + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass({ RequestSpecification.class, RestAssuredRestDocumentation.class }) + @EnableConfigurationProperties(RestDocsProperties.class) + static class RestDocsRestAssuredConfiguration { + + @Bean + @ConditionalOnMissingBean + RequestSpecification restDocsRestAssuredConfigurer( + ObjectProvider configurationCustomizers, + RestDocumentationContextProvider contextProvider) { + RestAssuredRestDocumentationConfigurer configurer = RestAssuredRestDocumentation + .documentationConfiguration(contextProvider); + configurationCustomizers.orderedStream() + .forEach((configurationCustomizer) -> configurationCustomizer.customize(configurer)); + return new RequestSpecBuilder().addFilter(configurer).build(); + } + + @Bean + RestDocsRestAssuredBuilderCustomizer restAssuredBuilderCustomizer(RestDocsProperties properties, + RequestSpecification configurer) { + return new RestDocsRestAssuredBuilderCustomizer(properties, configurer); + } + + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(WebTestClientRestDocumentation.class) @ConditionalOnWebApplication(type = Type.REACTIVE) diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredBuilderCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredBuilderCustomizer.java new file mode 100644 index 00000000000..b87dbdf3450 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredBuilderCustomizer.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2019 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 + * + * https://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.boot.context.properties.PropertyMapper; +import org.springframework.util.StringUtils; + +/** + * A customizer that configures Spring REST Docs with REST Assured. + * + * @author Eddú Meléndez + */ +class RestDocsRestAssuredBuilderCustomizer implements InitializingBean { + + private final RestDocsProperties properties; + + private final RequestSpecification delegate; + + RestDocsRestAssuredBuilderCustomizer(RestDocsProperties properties, RequestSpecification delegate) { + this.properties = properties; + this.delegate = delegate; + } + + @Override + public void afterPropertiesSet() throws Exception { + PropertyMapper map = PropertyMapper.get(); + String host = this.properties.getUriHost(); + map.from(this.properties::getUriScheme) + .when((scheme) -> StringUtils.hasText(scheme) && StringUtils.hasText(host)) + .to((scheme) -> this.delegate.baseUri(scheme + "://" + host)); + map.from(this.properties::getUriPort).whenNonNull().to(this.delegate::port); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredConfigurationCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredConfigurationCustomizer.java new file mode 100644 index 00000000000..c15496100ea --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsRestAssuredConfigurationCustomizer.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.restassured.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 @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-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests.java new file mode 100644 index 00000000000..c869a947246 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests.java @@ -0,0 +1,106 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +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.testsupport.BuildOutput; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.annotation.Bean; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.templates.TemplateFormats; +import org.springframework.util.FileSystemUtils; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.hamcrest.Matchers.is; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyUris; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; + +/** + * Integration tests for advanced configuration of + * {@link AutoConfigureRestDocs @AutoConfigureRestDocs} with REST Assured. + * + * @author Eddú Meléndez + */ +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@AutoConfigureRestDocs +class RestAssuredRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests { + + @LocalServerPort + private int port; + + @Autowired + private RequestSpecification documentationSpec; + + private File generatedSnippets; + + @BeforeEach + void deleteSnippets() { + this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(), "generated-snippets"); + FileSystemUtils.deleteRecursively(this.generatedSnippets); + } + + @Test + void snippetGeneration() { + 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(this.generatedSnippets, "default-snippets"); + assertThat(defaultSnippetsDir).exists(); + assertThat(contentOf(new File(defaultSnippetsDir, "curl-request.md"))).contains("'https://api.example.com/'"); + assertThat(contentOf(new File(defaultSnippetsDir, "http-request.md"))).contains("api.example.com"); + assertThat(new File(defaultSnippetsDir, "http-response.md")).isFile(); + assertThat(new File(defaultSnippetsDir, "response-fields.md")).isFile(); + } + + @TestConfiguration(proxyBeanMethods = false) + static class CustomizationConfiguration { + + @Bean + RestDocumentationResultHandler restDocumentation() { + return MockMvcRestDocumentation.document("{method-name}"); + } + + @Bean + RestDocsRestAssuredConfigurationCustomizer templateFormatCustomizer() { + return (configurer) -> configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); + } + + @Bean + RestDocsRestAssuredConfigurationCustomizer defaultSnippetsCustomizer() { + return (configurer) -> configurer.snippets() + .withAdditionalDefaults(responseFields(fieldWithPath("_links.self").description("Main URL"))); + } + + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredRestDocsAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredRestDocsAutoConfigurationIntegrationTests.java new file mode 100644 index 00000000000..092daf284e9 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestAssuredRestDocsAutoConfigurationIntegrationTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +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.testsupport.BuildOutput; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.util.FileSystemUtils; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.hamcrest.Matchers.is; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyUris; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; + +/** + * Integration tests for {@link RestDocsAutoConfiguration} with REST Assured. + * + * @author Eddú Meléndez + */ +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@AutoConfigureRestDocs +class RestAssuredRestDocsAutoConfigurationIntegrationTests { + + @LocalServerPort + private int port; + + @Autowired + private RequestSpecification documentationSpec; + + private File generatedSnippets; + + @BeforeEach + void deleteSnippets() { + this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(), "generated-snippets"); + FileSystemUtils.deleteRecursively(this.generatedSnippets); + } + + @Test + void defaultSnippetsAreWritten() { + 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(this.generatedSnippets, "default-snippets"); + assertThat(defaultSnippetsDir).exists(); + assertThat(contentOf(new File(defaultSnippetsDir, "curl-request.adoc"))).contains("'https://api.example.com/'"); + assertThat(contentOf(new File(defaultSnippetsDir, "http-request.adoc"))).contains("api.example.com"); + assertThat(new File(defaultSnippetsDir, "http-response.adoc")).isFile(); + } + +}