diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/RestDocumentationResultHandler.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/RestDocumentationResultHandler.java index a5c12334..3111b7b6 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/RestDocumentationResultHandler.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/RestDocumentationResultHandler.java @@ -49,10 +49,7 @@ public class RestDocumentationResultHandler implements ResultHandler { @Override public void handle(MvcResult result) throws Exception { - @SuppressWarnings("unchecked") - Map configuration = (Map) result.getRequest() - .getAttribute(ATTRIBUTE_NAME_CONFIGURATION); - this.delegate.handle(result.getRequest(), result.getResponse(), configuration); + this.delegate.handle(result.getRequest(), result.getResponse(), retrieveConfiguration(result)); } /** @@ -75,9 +72,7 @@ public class RestDocumentationResultHandler implements ResultHandler { @Override public void handle(MvcResult result) throws Exception { - @SuppressWarnings("unchecked") - Map configuration = new HashMap<>( - (Map) result.getRequest().getAttribute(ATTRIBUTE_NAME_CONFIGURATION)); + Map configuration = new HashMap<>(retrieveConfiguration(result)); configuration.remove(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS); getDelegate().handle(result.getRequest(), result.getResponse(), configuration); } @@ -93,4 +88,13 @@ public class RestDocumentationResultHandler implements ResultHandler { return this.delegate; } + private Map retrieveConfiguration(MvcResult result) { + @SuppressWarnings("unchecked") + Map configuration = (Map) result.getRequest() + .getAttribute(ATTRIBUTE_NAME_CONFIGURATION); + Assert.state(configuration != null, () -> "REST Docs configuration not found. Did you forget to apply a " + + MockMvcRestDocumentationConfigurer.class.getSimpleName() + " when building the MockMvc instance?"); + return configuration; + } + } diff --git a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java index ed8872e8..129952b7 100644 --- a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java +++ b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java @@ -69,6 +69,7 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; @@ -491,6 +492,26 @@ public class MockMvcRestDocumentationIntegrationTests { + " -H 'Accept: application/json'")))); } + @Test + public void exceptionShouldBeThrownWhenCallDocumentMockMvcNotConfigured() { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + assertThatThrownBy(() -> mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)).andDo(document("basic"))) + .isInstanceOf(IllegalStateException.class).hasMessage("REST Docs configuration not found. Did you " + + "forget to apply a MockMvcRestDocumentationConfigurer when building the MockMvc instance?"); + + } + + @Test + public void exceptionShouldBeThrownWhenCallDocumentSnippetsMockMvcNotConfigured() { + RestDocumentationResultHandler documentation = document("{method-name}-{step}"); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + assertThatThrownBy(() -> mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) + .andDo(documentation.document(responseHeaders(headerWithName("a").description("one"))))) + .isInstanceOf(IllegalStateException.class) + .hasMessage("REST Docs configuration not found. Did you forget to apply a " + + "MockMvcRestDocumentationConfigurer when building the MockMvc instance?"); + } + @Test public void multiPart() throws Exception { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java index b3e730e2..342d69eb 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java @@ -67,8 +67,7 @@ public class RestDocumentationFilter implements Filter { * @return the configuration */ protected Map getConfiguration(FilterableRequestSpecification requestSpec, FilterContext context) { - Map configuration = new HashMap<>( - context.>getValue(CONTEXT_KEY_CONFIGURATION)); + Map configuration = new HashMap<>(retrieveConfiguration(context)); configuration.put(RestDocumentationContext.class.getName(), context.getValue(RestDocumentationContext.class.getName())); configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, requestSpec.getUserDefinedPath()); @@ -97,4 +96,13 @@ public class RestDocumentationFilter implements Filter { }; } + private static Map retrieveConfiguration(FilterContext context) { + Map configuration = context.getValue(CONTEXT_KEY_CONFIGURATION); + Assert.state(configuration != null, + () -> "REST Docs configuration not found. Did you forget to add a " + + RestAssuredRestDocumentationConfigurer.class.getSimpleName() + + " as a filter when building the RequestSpecification?"); + return configuration; + } + } diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java index a5206105..492e71b2 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java @@ -47,6 +47,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; @@ -339,6 +340,25 @@ public class RestAssuredRestDocumentationIntegrationTests { .hasContent("Custom curl request"); } + @Test + public void exceptionShouldBeThrownWhenCallDocumentRequestSpecificationNotConfigured() { + assertThatThrownBy(() -> given().port(tomcat.getPort()).filter(document("default")).get("/")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("REST Docs configuration not found. Did you forget to add a " + + "RestAssuredRestDocumentationConfigurer as a filter when building the RequestSpecification?"); + } + + @Test + public void exceptionShouldBeThrownWhenCallDocumentSnippetsRequestSpecificationNotConfigured() { + RestDocumentationFilter documentation = document("{method-name}-{step}"); + assertThatThrownBy(() -> given().port(tomcat.getPort()) + .filter(documentation.document(responseHeaders(headerWithName("a").description("one")))).get("/")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("REST Docs configuration not found. Did you forget to add a " + + "RestAssuredRestDocumentationConfigurer as a filter when building the " + + "RequestSpecification?"); + } + private void assertExpectedSnippetFilesExist(File directory, String... snippets) { for (String snippet : snippets) { assertThat(new File(directory, snippet)).isFile(); diff --git a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentation.java b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentation.java index 1dd60c17..ce66df5f 100644 --- a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentation.java +++ b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentation.java @@ -16,7 +16,6 @@ package org.springframework.restdocs.webtestclient; -import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; @@ -134,8 +133,8 @@ public abstract class WebTestClientRestDocumentation { } private static Map retrieveConfiguration(ExchangeResult result) { - Map configuration = new HashMap<>( - WebTestClientRestDocumentationConfigurer.retrieveConfiguration(result.getRequestHeaders())); + Map configuration = WebTestClientRestDocumentationConfigurer + .retrieveConfiguration(result.getRequestHeaders()); configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, result.getUriTemplate()); return configuration; } diff --git a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java index f210d3ed..e6d5299d 100644 --- a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java +++ b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java @@ -29,6 +29,7 @@ import org.springframework.restdocs.RestDocumentationContext; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.config.RestDocumentationConfigurer; import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; @@ -78,7 +79,10 @@ public class WebTestClientRestDocumentationConfigurer extends static Map retrieveConfiguration(HttpHeaders headers) { String requestId = headers.getFirst(WebTestClient.WEBTESTCLIENT_REQUEST_ID); - return configurations.remove(requestId); + Map configuration = configurations.remove(requestId); + Assert.state(configuration != null, () -> "REST Docs configuration not found. Did you forget to register a " + + WebTestClientRestDocumentationConfigurer.class.getSimpleName() + " as a filter?"); + return configuration; } @Override diff --git a/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java b/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java index 920b8582..74a3a4aa 100644 --- a/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java +++ b/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java @@ -29,6 +29,7 @@ import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ExchangeFunction; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -51,7 +52,8 @@ public class WebTestClientRestDocumentationConfigurerTests { .header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build(); this.configurer.filter(request, mock(ExchangeFunction.class)); assertThat(WebTestClientRestDocumentationConfigurer.retrieveConfiguration(request.headers())).isNotNull(); - assertThat(WebTestClientRestDocumentationConfigurer.retrieveConfiguration(request.headers())).isNull(); + assertThatIllegalStateException() + .isThrownBy(() -> WebTestClientRestDocumentationConfigurer.retrieveConfiguration(request.headers())); } @Test diff --git a/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationIntegrationTests.java b/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationIntegrationTests.java index ae3766c8..06199f8c 100644 --- a/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationIntegrationTests.java +++ b/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationIntegrationTests.java @@ -23,6 +23,7 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -58,6 +59,7 @@ import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.partWithName; @@ -173,6 +175,16 @@ public class WebTestClientRestDocumentationIntegrationTests { + " 'Accept:application/json' \\%n" + " 'Cookie:cookieName=cookieVal'")))); } + @Test + public void illegalStateExceptionShouldBeThrownWhenCallDocumentWebClientNotConfigured() { + assertThatThrownBy(() -> this.webTestClient + .mutateWith((builder, httpHandlerBuilder, connector) -> builder.filters(List::clear).build()).get() + .uri("/").exchange().expectBody().consumeWith(document("default-snippets"))) + .isInstanceOf(IllegalStateException.class) + .hasMessage("REST Docs configuration not found. Did you forget to register a " + + "WebTestClientRestDocumentationConfigurer as a filter?"); + } + private void assertExpectedSnippetFilesExist(File directory, String... snippets) { Set actual = new HashSet<>(Arrays.asList(directory.listFiles())); Set expected = Stream.of(snippets).map((snippet) -> new File(directory, snippet))