From 4f8b17383684c08a2b12cae1b561db5cf0cfae0b Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Sat, 2 Sep 2017 10:35:11 +0200 Subject: [PATCH 1/2] Add support for configuring default request and response preprocessors See gh-424 --- docs/src/docs/asciidoc/configuration.adoc | 20 ++++ .../customizing-requests-and-responses.adoc | 18 +-- .../CustomDefaultOperationPreprocessors.java | 50 +++++++++ .../mockmvc/EveryTestPreprocessing.java | 15 +-- .../CustomDefaultOperationPreprocessors.java | 49 ++++++++ .../restassured/EveryTestPreprocessing.java | 17 +-- .../OperationPreprocessorsConfigurer.java | 82 ++++++++++++++ .../config/RestDocumentationConfigurer.java | 13 ++- .../generate/RestDocumentationGenerator.java | 61 +++++++++- .../RestDocumentationGeneratorTests.java | 105 +++++++++++++++++- .../RestDocumentationConfigurerTests.java | 57 +++++++++- ...ckMvcOperationPreprocessorsConfigurer.java | 49 ++++++++ .../MockMvcRestDocumentationConfigurer.java | 12 +- .../RestDocumentationResultHandler.java | 3 + ...kMvcRestDocumentationIntegrationTests.java | 67 +++++++++++ ...suredOperationPreprocessorsConfigurer.java | 48 ++++++++ ...estAssuredRestDocumentationConfigurer.java | 12 +- .../restassured3/RestDocumentationFilter.java | 4 + ...suredRestDocumentationConfigurerTests.java | 18 ++- ...uredRestDocumentationIntegrationTests.java | 51 +++++++++ 20 files changed, 699 insertions(+), 52 deletions(-) create mode 100644 docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java create mode 100644 docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java create mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java create mode 100644 spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java create mode 100644 spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java diff --git a/docs/src/docs/asciidoc/configuration.adoc b/docs/src/docs/asciidoc/configuration.adoc index af45dad3..35490f79 100644 --- a/docs/src/docs/asciidoc/configuration.adoc +++ b/docs/src/docs/asciidoc/configuration.adoc @@ -114,3 +114,23 @@ include::{examples-dir}/com/example/mockmvc/CustomDefaultSnippets.java[tags=cust ---- include::{examples-dir}/com/example/restassured/CustomDefaultSnippets.java[tags=custom-default-snippets] ---- + +[[configuration-default-preprocessors]] +=== Operation preprocessors + +You can configure default Request / Response preprocessors during setup using the +`RestDocumentationConfigurer` API. For example, to remove the `Foo` headers from all requests +and pretty print all responses: + +[source,java,indent=0,role="primary"] +.MockMvc +---- +include::{examples-dir}/com/example/mockmvc/CustomDefaultOperationPreprocessors.java[tags=custom-default-preprocessors] +---- + +[source,java,indent=0,role="secondary"] +.REST Assured +---- +include::{examples-dir}/com/example/restassured/CustomDefaultOperationPreprocessors.java[tags=custom-default-preprocessors] +---- + diff --git a/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc b/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc index 28d6d754..d68f7314 100644 --- a/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc +++ b/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc @@ -27,29 +27,20 @@ include::{examples-dir}/com/example/restassured/PerTestPreprocessing.java[tags=p <2> Apply a response preprocessor that will pretty print its content. Alternatively, you may want to apply the same preprocessors to every test. You can do -so by configuring the preprocessors in your `@Before` method and using the -<>: +so by configuring the preprocessors using the `RestDocumentationConfigurer` API. +For example to remove the `Foo` header from all requests and pretty print all responses: [source,java,indent=0,role="primary"] .MockMvc ---- include::{examples-dir}/com/example/mockmvc/EveryTestPreprocessing.java[tags=setup] ---- -<1> Create a `RestDocumentationResultHandler`, configured to preprocess the request - and response. -<2> Create a `MockMvc` instance, configured to always call the documentation result - handler. [source,java,indent=0,role="secondary"] .REST Assured ---- include::{examples-dir}/com/example/restassured/EveryTestPreprocessing.java[tags=setup] ---- -<1> Create a `RestDocumentationFilter`, configured to preprocess the request - and response. -<2> Create a `RequestSpecification` instance, configured to always call the documentation - filter. Then, in each test, any configuration specific to that test can be performed. For example: @@ -58,17 +49,12 @@ Then, in each test, any configuration specific to that test can be performed. Fo ---- include::{examples-dir}/com/example/mockmvc/EveryTestPreprocessing.java[tags=use] ---- -<1> The request and response will be preprocessed due to the use of `alwaysDo` above. -<2> Document the links specific to the resource that is being tested [source,java,indent=0,role="secondary"] .REST Assured ---- include::{examples-dir}/com/example/restassured/EveryTestPreprocessing.java[tags=use] ---- -<1> The request and response will be preprocessed due to the configuration of the -`RequestSpecification` in the `setUp` method. -<2> Document the links specific to the resource that is being tested Various built in preprocessors, including those illustrated above, are available via the static methods on `Preprocessors`. See <> for further details. diff --git a/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java b/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java new file mode 100644 index 00000000..786c050e --- /dev/null +++ b/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java @@ -0,0 +1,50 @@ +/* + * Copyright 2014-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 com.example.mockmvc; + +import org.junit.Before; +import org.junit.Rule; + +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; + +public class CustomDefaultOperationPreprocessors { + + @Rule + public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(); + + private WebApplicationContext context; + + private MockMvc mockMvc; + + @Before + public void setup() { + // tag::custom-default-preprocessors[] + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withDefaultRequestPreprocessors(removeHeaders("Foo")) + .withDefaultResponsePreprocessors(prettyPrint())) + .build(); + // end::custom-default-preprocessors[] + } +} diff --git a/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java b/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java index 934a353e..279a3310 100644 --- a/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java +++ b/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java @@ -19,7 +19,6 @@ package com.example.mockmvc; import org.junit.Before; import org.junit.Rule; import org.springframework.restdocs.JUnitRestDocumentation; -import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @@ -29,8 +28,6 @@ import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.li import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -45,16 +42,12 @@ public class EveryTestPreprocessing { // tag::setup[] private MockMvc mockMvc; - private RestDocumentationResultHandler documentationHandler; - @Before public void setup() { - this.documentationHandler = document("{method-name}", // <1> - preprocessRequest(removeHeaders("Foo")), - preprocessResponse(prettyPrint())); this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(documentationConfiguration(this.restDocumentation)) - .alwaysDo(this.documentationHandler) // <2> + .apply(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withDefaultRequestPreprocessors(removeHeaders("Foo")) + .withDefaultResponsePreprocessors(prettyPrint())) .build(); } @@ -64,7 +57,7 @@ public class EveryTestPreprocessing { // tag::use[] this.mockMvc.perform(get("/")) // <1> .andExpect(status().isOk()) - .andDo(this.documentationHandler.document( // <2> + .andDo(document("{method-name}", links(linkWithRel("self").description("Canonical self link")) )); // end::use[] diff --git a/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java b/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java new file mode 100644 index 00000000..c4ebd8ff --- /dev/null +++ b/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java @@ -0,0 +1,49 @@ +/* + * Copyright 2014-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. + * 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 com.example.restassured; + +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; + +import org.junit.Before; +import org.junit.Rule; + +import org.springframework.restdocs.JUnitRestDocumentation; + +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; + +public class CustomDefaultOperationPreprocessors { + + @Rule + public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(); + + @SuppressWarnings("unused") + private RequestSpecification spec; + + @Before + public void setup() { + // tag::custom-default-preprocessors[] + this.spec = new RequestSpecBuilder() + .addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withDefaultRequestPreprocessors(removeHeaders("Foo")) + .withDefaultResponsePreprocessors(prettyPrint())) + .build(); + // end::custom-default-preprocessors[] + } +} diff --git a/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java b/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java index e280fe45..fa14f5c2 100644 --- a/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java +++ b/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java @@ -23,13 +23,10 @@ import org.junit.Before; import org.junit.Rule; import org.springframework.restdocs.JUnitRestDocumentation; -import org.springframework.restdocs.restassured3.RestDocumentationFilter; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; @@ -43,16 +40,12 @@ public class EveryTestPreprocessing { // tag::setup[] private RequestSpecification spec; - private RestDocumentationFilter documentationFilter; - @Before public void setup() { - this.documentationFilter = document("{method-name}", - preprocessRequest(removeHeaders("Foo")), - preprocessResponse(prettyPrint())); // <1> this.spec = new RequestSpecBuilder() - .addFilter(documentationConfiguration(this.restDocumentation)) - .addFilter(this.documentationFilter)// <2> + .addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withDefaultRequestPreprocessors(removeHeaders("Foo")) + .withDefaultResponsePreprocessors(prettyPrint())) .build(); } @@ -60,8 +53,8 @@ public class EveryTestPreprocessing { public void use() throws Exception { // tag::use[] - RestAssured.given(this.spec) // <1> - .filter(this.documentationFilter.document( // <2> + RestAssured.given(this.spec) + .filter(document("{method-name]", links(linkWithRel("self").description("Canonical self link")))) .when().get("/") .then().assertThat().statusCode(is(200)); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java new file mode 100644 index 00000000..afb21cc5 --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java @@ -0,0 +1,82 @@ +/* + * Copyright 2014-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.restdocs.config; + +import java.util.Map; + +import org.springframework.restdocs.RestDocumentationContext; +import org.springframework.restdocs.generate.RestDocumentationGenerator; +import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; +import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor; +import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor; +import org.springframework.restdocs.operation.preprocess.Preprocessors; + +/** + * A configurer that can be used to configure the default operation preprocessors that need to be used. + * + * @param The type of the configurer's parent + * @param The concrete type of the configurer to be returned from chained methods + * @author Filip Hrisafov + * @since 2.0.0 + */ +public abstract class OperationPreprocessorsConfigurer + extends AbstractNestedConfigurer { + + private OperationRequestPreprocessor defaultOperationRequestPreprocessor; + private OperationResponsePreprocessor defaultOperationResponsePreprocessor; + + /** + * Creates a new {@code OperationPreprocessorConfigurer} with the given {@code parent}. + * + * @param parent the parent + */ + protected OperationPreprocessorsConfigurer(PARENT parent) { + super(parent); + } + + @Override + public void apply(Map configuration, RestDocumentationContext context) { + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, + this.defaultOperationRequestPreprocessor); + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, + this.defaultOperationResponsePreprocessor); + } + + /** + * Configures the default documentation operation request preprocessors. + * + * @param preprocessors the preprocessors + * @return {@code this} + */ + @SuppressWarnings("unchecked") + public TYPE withDefaultRequestPreprocessors(OperationPreprocessor... preprocessors) { + this.defaultOperationRequestPreprocessor = Preprocessors.preprocessRequest(preprocessors); + return (TYPE) this; + } + + /** + * Configures the default documentation operation response preprocessors. + * + * @param preprocessors the preprocessors + * @return {@code this} + */ + @SuppressWarnings("unchecked") + public TYPE withDefaultResponsePreprocessors(OperationPreprocessor... preprocessors) { + this.defaultOperationResponsePreprocessor = Preprocessors.preprocessResponse(preprocessors); + return (TYPE) this; + } +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java index 59444e65..75b69352 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java @@ -36,12 +36,14 @@ import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine; * Abstract base class for the configuration of Spring REST Docs. * * @param The concrete type of the {@link SnippetConfigurer}. + * @param

The concrete type of the {@link OperationPreprocessorsConfigurer} * @param The concrete type of this configurer, to be returned from methods that * support chaining * @author Andy Wilkinson + * @author Filip Hrisafov * @since 1.1.0 */ -public abstract class RestDocumentationConfigurer { +public abstract class RestDocumentationConfigurer { private final WriterResolverConfigurer writerResolverConfigurer = new WriterResolverConfigurer(); @@ -55,6 +57,14 @@ public abstract class RestDocumentationConfigurer configuration, RestDocumentationContext context) { List configurers = Arrays.asList(snippets(), + operationPreprocessors(), this.templateEngineConfigurer, this.writerResolverConfigurer); for (AbstractConfigurer configurer : configurers) { configurer.apply(configuration, context); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java index d21b2ad7..d239ffc4 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java @@ -41,6 +41,7 @@ import org.springframework.util.Assert; * @param the request type that can be handled * @param the response type that can be handled * @author Andy Wilkinson + * @author Filip Hrisafov * @since 1.1.0 */ public final class RestDocumentationGenerator { @@ -55,6 +56,19 @@ public final class RestDocumentationGenerator { */ public static final String ATTRIBUTE_NAME_DEFAULT_SNIPPETS = "org.springframework.restdocs.defaultSnippets"; + /** + * Name of the operation attribute used to hold the default operation request preprocessor. + */ + public static final String ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR = + "org.springframework.restdocs.defaultOperationRequestPreprocessor"; + + /** + * Name of the operation attribute used to hold the default operation response preprocessor. + */ + public static final String ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR = + "org.springframework.restdocs.defaultOperationResponsePreprocessor"; + + private final String identifier; private final OperationRequestPreprocessor requestPreprocessor; @@ -183,12 +197,9 @@ public final class RestDocumentationGenerator { * @throws RestDocumentationGenerationException if a failure occurs during handling */ public void handle(REQ request, RESP response, Map configuration) { - OperationRequest operationRequest = this.requestPreprocessor - .preprocess(this.requestConverter.convert(request)); - - OperationResponse operationResponse = this.responsePreprocessor - .preprocess(this.responseConverter.convert(response)); Map attributes = new HashMap<>(configuration); + OperationRequest operationRequest = preprocessRequest(request, attributes); + OperationResponse operationResponse = preprocessResponse(response, attributes); Operation operation = new StandardOperation(this.identifier, operationRequest, operationResponse, attributes); try { @@ -228,6 +239,46 @@ public final class RestDocumentationGenerator { return combinedSnippets; } + private OperationRequest preprocessRequest(REQ request, Map configuration) { + List requestPreprocessors = getRequestPreprocessors(configuration); + OperationRequest operationRequest = this.requestConverter.convert(request); + for (OperationRequestPreprocessor preprocessor : requestPreprocessors) { + operationRequest = preprocessor.preprocess(operationRequest); + } + return operationRequest; + } + + private List getRequestPreprocessors(Map configuration) { + List preprocessors = new ArrayList<>(2); + preprocessors.add(this.requestPreprocessor); + OperationRequestPreprocessor defaultRequestPreprocessor = (OperationRequestPreprocessor) configuration.get( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); + if (defaultRequestPreprocessor != null) { + preprocessors.add(defaultRequestPreprocessor); + } + return preprocessors; + } + + private OperationResponse preprocessResponse(RESP response, Map configuration) { + List responsePreprocessors = getResponsePreprocessors(configuration); + OperationResponse operationResponse = this.responseConverter.convert(response); + for (OperationResponsePreprocessor preprocessor : responsePreprocessors) { + operationResponse = preprocessor.preprocess(operationResponse); + } + return operationResponse; + } + + private List getResponsePreprocessors(Map configuration) { + List preprocessors = new ArrayList<>(2); + preprocessors.add(this.responsePreprocessor); + OperationResponsePreprocessor defaultResponsePreprocessor = (OperationResponsePreprocessor) configuration.get( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); + if (defaultResponsePreprocessor != null) { + preprocessors.add(defaultResponsePreprocessor); + } + return preprocessors; + } + private static final class IdentityOperationRequestPreprocessor implements OperationRequestPreprocessor { diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java index 44fcb6e8..f06700a2 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java @@ -35,8 +35,10 @@ import org.springframework.restdocs.operation.OperationResponse; import org.springframework.restdocs.operation.OperationResponseFactory; import org.springframework.restdocs.operation.RequestConverter; import org.springframework.restdocs.operation.ResponseConverter; +import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor; import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor; +import org.springframework.restdocs.operation.preprocess.Preprocessors; import org.springframework.restdocs.snippet.Snippet; import static org.hamcrest.CoreMatchers.equalTo; @@ -51,6 +53,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; * Tests for {@link RestDocumentationGenerator}. * * @author Andy Wilkinson + * @author Filip Hrisafov */ public class RestDocumentationGeneratorTests { @@ -75,6 +78,9 @@ public class RestDocumentationGeneratorTests { private final Snippet snippet = mock(Snippet.class); + private final OperationPreprocessor requestPreprocessor = mock(OperationPreprocessor.class); + private final OperationPreprocessor responsePreprocessor = mock(OperationPreprocessor.class); + @Test public void basicHandling() throws IOException { given(this.requestConverter.convert(this.request)) @@ -107,6 +113,84 @@ public class RestDocumentationGeneratorTests { verifySnippetInvocation(defaultSnippet2, configuration); } + @Test + public void defaultOperationRequestPreprocessorsAreCalled() throws IOException { + given(this.requestConverter.convert(this.request)) + .willReturn(this.operationRequest); + given(this.responseConverter.convert(this.response)) + .willReturn(this.operationResponse); + HashMap configuration = new HashMap<>(); + OperationPreprocessor defaultPreprocessor1 = mock(OperationPreprocessor.class); + OperationPreprocessor defaultPreprocessor2 = mock(OperationPreprocessor.class); + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, + Preprocessors.preprocessRequest(defaultPreprocessor1, defaultPreprocessor2)); + OperationRequest first = createRequest(); + OperationRequest second = createRequest(); + OperationRequest third = createRequest(); + given(this.requestPreprocessor.preprocess(this.operationRequest)).willReturn(first); + given(defaultPreprocessor1.preprocess(first)).willReturn(second); + given(defaultPreprocessor2.preprocess(second)).willReturn(third); + new RestDocumentationGenerator<>("id", this.requestConverter, + this.responseConverter, Preprocessors.preprocessRequest(this.requestPreprocessor), this.snippet) + .handle(this.request, this.response, configuration); + + verifySnippetInvocation(this.snippet, third, this.operationResponse, configuration, 1); + } + + @Test + public void defaultOperationResponsePreprocessorsAreCalled() throws IOException { + given(this.requestConverter.convert(this.request)) + .willReturn(this.operationRequest); + given(this.responseConverter.convert(this.response)) + .willReturn(this.operationResponse); + HashMap configuration = new HashMap<>(); + OperationPreprocessor defaultPreprocessor1 = mock(OperationPreprocessor.class); + OperationPreprocessor defaultPreprocessor2 = mock(OperationPreprocessor.class); + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, + Preprocessors.preprocessResponse(defaultPreprocessor1, defaultPreprocessor2)); + OperationResponse first = createResponse(); + OperationResponse second = createResponse(); + OperationResponse third = new OperationResponseFactory().createFrom(this.operationResponse, new HttpHeaders()); + given(this.responsePreprocessor.preprocess(this.operationResponse)).willReturn(first); + given(defaultPreprocessor1.preprocess(first)).willReturn(second); + given(defaultPreprocessor2.preprocess(second)).willReturn(third); + new RestDocumentationGenerator<>("id", this.requestConverter, + this.responseConverter, Preprocessors.preprocessResponse(this.responsePreprocessor), this.snippet) + .handle(this.request, this.response, configuration); + + verifySnippetInvocation(this.snippet, this.operationRequest, third, configuration, 1); + } + + @Test + public void defaultOperationPreprocessorsAreCalled() throws IOException { + given(this.requestConverter.convert(this.request)) + .willReturn(this.operationRequest); + given(this.responseConverter.convert(this.response)) + .willReturn(this.operationResponse); + HashMap configuration = new HashMap<>(); + OperationPreprocessor requestPreprocessor1 = mock(OperationPreprocessor.class); + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, + Preprocessors.preprocessRequest(requestPreprocessor1)); + OperationRequest firstRequest = createRequest(); + OperationRequest secondRequest = createRequest(); + given(this.requestPreprocessor.preprocess(this.operationRequest)).willReturn(firstRequest); + given(requestPreprocessor1.preprocess(firstRequest)).willReturn(secondRequest); + + OperationPreprocessor responsePreprocessor1 = mock(OperationPreprocessor.class); + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, + Preprocessors.preprocessResponse(responsePreprocessor1)); + OperationResponse firstResponse = createResponse(); + OperationResponse secondResponse = createResponse(); + given(this.responsePreprocessor.preprocess(this.operationResponse)).willReturn(firstResponse); + given(responsePreprocessor1.preprocess(firstResponse)).willReturn(secondResponse); + new RestDocumentationGenerator<>("id", this.requestConverter, + this.responseConverter, Preprocessors.preprocessRequest(this.requestPreprocessor), + Preprocessors.preprocessResponse(this.responsePreprocessor), this.snippet) + .handle(this.request, this.response, configuration); + + verifySnippetInvocation(this.snippet, secondRequest, secondResponse, configuration, 1); + } + @Test public void newGeneratorOnlyCallsItsSnippets() throws IOException { OperationRequestPreprocessor requestPreprocessor = mock( @@ -141,12 +225,27 @@ public class RestDocumentationGeneratorTests { private void verifySnippetInvocation(Snippet snippet, Map attributes, int times) throws IOException { + verifySnippetInvocation(snippet, this.operationRequest, this.operationResponse, attributes, times); + } + + private void verifySnippetInvocation(Snippet snippet, OperationRequest operationRequest, + OperationResponse operationResponse, + Map attributes, int times) throws IOException { ArgumentCaptor operation = ArgumentCaptor.forClass(Operation.class); verify(snippet, Mockito.times(times)).document(operation.capture()); - assertThat(this.operationRequest, is(equalTo(operation.getValue().getRequest()))); - assertThat(this.operationResponse, - is(equalTo(operation.getValue().getResponse()))); + assertThat(operationRequest, is(equalTo(operation.getValue().getRequest()))); + assertThat(operationResponse, is(equalTo(operation.getValue().getResponse()))); assertThat(attributes, is(equalTo(operation.getValue().getAttributes()))); } + private static OperationRequest createRequest() { + return new OperationRequestFactory() + .create(URI.create("http://localhost:8080"), null, null, new HttpHeaders(), null, null); + } + + private static OperationResponse createResponse() { + return new OperationResponseFactory() + .create(null, null, null); + } + } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java index 4cc0b635..a56c5646 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java @@ -31,6 +31,9 @@ import org.springframework.restdocs.cli.HttpieRequestSnippet; import org.springframework.restdocs.generate.RestDocumentationGenerator; import org.springframework.restdocs.http.HttpRequestSnippet; import org.springframework.restdocs.http.HttpResponseSnippet; +import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor; +import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor; +import org.springframework.restdocs.operation.preprocess.Preprocessors; import org.springframework.restdocs.payload.RequestBodySnippet; import org.springframework.restdocs.payload.ResponseBodySnippet; import org.springframework.restdocs.snippet.Snippet; @@ -45,6 +48,7 @@ import org.springframework.test.util.ReflectionTestUtils; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.hasEntry; import static org.junit.Assert.assertThat; @@ -54,6 +58,7 @@ import static org.mockito.Mockito.mock; * Tests for {@link RestDocumentationConfigurer}. * * @author Andy Wilkinson + * @author Filip Hrisafov */ public class RestDocumentationConfigurerTests { @@ -88,6 +93,14 @@ public class RestDocumentationConfigurerTests { assertThat(snippetConfiguration.getEncoding(), is(equalTo("UTF-8"))); assertThat(snippetConfiguration.getTemplateFormat(), is(equalTo(TemplateFormats.asciidoctor()))); + + OperationRequestPreprocessor defaultOperationRequestPreprocessor = (OperationRequestPreprocessor) + configuration.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); + assertThat(defaultOperationRequestPreprocessor, is(nullValue())); + + OperationResponsePreprocessor defaultOperationResponsePreprocessor = (OperationResponsePreprocessor) + configuration.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); + assertThat(defaultOperationResponsePreprocessor, is(nullValue())); } @Test @@ -200,6 +213,32 @@ public class RestDocumentationConfigurerTests { assertThat(templateContext.size(), equalTo(0)); } + @Test + public void customDefaultOperationRequestPreprocessor() { + Map configuration = new HashMap<>(); + this.configurer.operationPreprocessors() + .withDefaultRequestPreprocessors(Preprocessors.prettyPrint(), Preprocessors.removeHeaders("Foo")) + .apply(configuration, createContext()); + assertThat(configuration, + hasEntry( + equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR), + instanceOf(OperationRequestPreprocessor.class))); + //TODO how can we actually test that the preprocessors that we set are actually there? + } + + @Test + public void customDefaultOperationResponsePreprocessor() { + Map configuration = new HashMap<>(); + this.configurer.operationPreprocessors() + .withDefaultResponsePreprocessors(Preprocessors.prettyPrint(), Preprocessors.removeHeaders("Foo")) + .apply(configuration, createContext()); + assertThat(configuration, + hasEntry( + equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR), + instanceOf(OperationResponsePreprocessor.class))); + //TODO same as for the customDefaultOperationRequestPreprocessor + } + private RestDocumentationContext createContext() { ManualRestDocumentation manualRestDocumentation = new ManualRestDocumentation( "build"); @@ -209,16 +248,24 @@ public class RestDocumentationConfigurerTests { } private static final class TestRestDocumentationConfigurer extends - RestDocumentationConfigurer { + RestDocumentationConfigurer { private final TestSnippetConfigurer snippetConfigurer = new TestSnippetConfigurer( this); + private final TestOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = + new TestOperationPreprocessorsConfigurer(this); + @Override public TestSnippetConfigurer snippets() { return this.snippetConfigurer; } + @Override + public TestOperationPreprocessorsConfigurer operationPreprocessors() { + return this.operationPreprocessorsConfigurer; + } } private static final class TestSnippetConfigurer extends @@ -230,4 +277,12 @@ public class RestDocumentationConfigurerTests { } + private static final class TestOperationPreprocessorsConfigurer extends + OperationPreprocessorsConfigurer { + + protected TestOperationPreprocessorsConfigurer(TestRestDocumentationConfigurer parent) { + super(parent); + } + } + } diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java new file mode 100644 index 00000000..d41df9ed --- /dev/null +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java @@ -0,0 +1,49 @@ +/* + * Copyright 2014-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.restdocs.mockmvc; + +import org.springframework.restdocs.config.OperationPreprocessorsConfigurer; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcConfigurer; +import org.springframework.web.context.WebApplicationContext; + +/** + * A configurer that can be used to configure the operation preprocessors. + * + * @author Filip Hrisafov + * @since 2.0.0 + */ +public final class MockMvcOperationPreprocessorsConfigurer extends + OperationPreprocessorsConfigurer + implements MockMvcConfigurer { + + MockMvcOperationPreprocessorsConfigurer(MockMvcRestDocumentationConfigurer parent) { + super(parent); + } + + @Override + public void afterConfigurerAdded(ConfigurableMockMvcBuilder builder) { + and().afterConfigurerAdded(builder); + } + + @Override + public RequestPostProcessor beforeMockMvcCreated( + ConfigurableMockMvcBuilder builder, WebApplicationContext context) { + return and().beforeMockMvcCreated(builder, context); + } +} diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java index 5c91186d..5606ba20 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java @@ -33,10 +33,12 @@ import org.springframework.web.context.WebApplicationContext; * A MockMvc-specific {@link RestDocumentationConfigurer}. * * @author Andy Wilkinson + * @author Filip Hrisafov * @since 1.1.0 */ public final class MockMvcRestDocumentationConfigurer extends - RestDocumentationConfigurer + RestDocumentationConfigurer implements MockMvcConfigurer { private final MockMvcSnippetConfigurer snippetConfigurer = new MockMvcSnippetConfigurer( @@ -44,6 +46,9 @@ public final class MockMvcRestDocumentationConfigurer extends private final UriConfigurer uriConfigurer = new UriConfigurer(this); + private final MockMvcOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = + new MockMvcOperationPreprocessorsConfigurer(this); + private final RestDocumentationContextProvider contextManager; MockMvcRestDocumentationConfigurer(RestDocumentationContextProvider contextManager) { @@ -76,6 +81,11 @@ public final class MockMvcRestDocumentationConfigurer extends return this.snippetConfigurer; } + @Override + public MockMvcOperationPreprocessorsConfigurer operationPreprocessors() { + return this.operationPreprocessorsConfigurer; + } + private final class ConfigurerApplyingRequestPostProcessor implements RequestPostProcessor { 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 44904365..5f255440 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 @@ -82,6 +82,9 @@ public class RestDocumentationResultHandler implements ResultHandler { .getAttribute(ATTRIBUTE_NAME_CONFIGURATION)); configuration.remove( RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS); + // TODO Do we need to remove the preprocessors here as well? + // I think that there is no test that evaluates this here. And the Javadoc does not reflect the + // behaviour getDelegate().handle(result.getRequest(), result.getResponse(), 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 3b6ed629..0a5979b1 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 @@ -103,6 +103,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Andy Wilkinson * @author Dewet Diener * @author Tomasz Kopczynski + * @author Filip Hrisafov */ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @@ -493,6 +494,44 @@ public class MockMvcRestDocumentationIntegrationTests { .withContents(preprocessedRequest.content(prettyPrinted)))); } + @Test + public void defaultPreprocessedRequest() throws Exception { + Pattern pattern = Pattern.compile("(\"alpha\")"); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation) + .operationPreprocessors() + .withDefaultRequestPreprocessors(prettyPrint(), + removeHeaders("a", HttpHeaders.HOST, + HttpHeaders.CONTENT_LENGTH), + replacePattern(pattern, "\"<>\""))) + .build(); + + + MvcResult result = mockMvc + .perform(get("/").header("a", "alpha").header("b", "bravo") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON).content("{\"a\":\"alpha\"}")) + .andDo(document("default-preprocessed-request")) + .andReturn(); + + HttpRequestMatcher preprocessedRequest = httpRequest(asciidoctor(), + RequestMethod.GET, "/"); + List removedHeaders = Arrays.asList("a", HttpHeaders.HOST, + HttpHeaders.CONTENT_LENGTH); + for (String headerName : iterable(result.getRequest().getHeaderNames())) { + if (!removedHeaders.contains(headerName)) { + preprocessedRequest.header(headerName, + result.getRequest().getHeader(headerName)); + } + } + String prettyPrinted = String.format("{%n \"a\" : \"<>\"%n}"); + assertThat( + new File( + "build/generated-snippets/default-preprocessed-request/http-request.adoc"), + is(snippet(asciidoctor()) + .withContents(preprocessedRequest.content(prettyPrinted)))); + } + @Test public void preprocessedResponse() throws Exception { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) @@ -529,6 +568,34 @@ public class MockMvcRestDocumentationIntegrationTests { .content(prettyPrinted)))); } + @Test + public void defaultPreprocessedResponse() throws Exception { + Pattern pattern = Pattern.compile("(\"alpha\")"); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation) + .operationPreprocessors() + .withDefaultResponsePreprocessors(prettyPrint(), maskLinks(), removeHeaders("a"), + replacePattern(pattern, "\"<>\""))) + .build(); + + + mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document("default-preprocessed-response")); + + String prettyPrinted = String.format("{%n \"a\" : \"<>\",%n \"links\" : " + + "[ {%n \"rel\" : \"rel\",%n \"href\" : \"...\"%n } ]%n}"); + assertThat( + new File( + "build/generated-snippets/default-preprocessed-response/http-response.adoc"), + is(snippet(asciidoctor()) + .withContents(httpResponse(asciidoctor(), HttpStatus.OK) + .header("Content-Type", "application/json;charset=UTF-8") + .header(HttpHeaders.CONTENT_LENGTH, + prettyPrinted.getBytes().length) + .content(prettyPrinted)))); + } + @Test public void customSnippetTemplate() throws Exception { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java new file mode 100644 index 00000000..db6cffcd --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java @@ -0,0 +1,48 @@ +/* + * Copyright 2014-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.restdocs.restassured3; + +import io.restassured.filter.Filter; +import io.restassured.filter.FilterContext; +import io.restassured.response.Response; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.FilterableResponseSpecification; + +import org.springframework.restdocs.config.OperationPreprocessorsConfigurer; + +/** + * A configurer that can be used to configure the operation preprocessors when + * using REST Assured 3. + * + * @author Filip Hrisafov + * @since 2.0.0 + */ +public final class RestAssuredOperationPreprocessorsConfigurer extends + OperationPreprocessorsConfigurer + implements Filter { + + RestAssuredOperationPreprocessorsConfigurer(RestAssuredRestDocumentationConfigurer parent) { + super(parent); + } + + @Override + public Response filter(FilterableRequestSpecification requestSpec, + FilterableResponseSpecification responseSpec, FilterContext context) { + return and().filter(requestSpec, responseSpec, context); + } +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java index b5a5b506..b8c71fbf 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java @@ -33,15 +33,20 @@ import org.springframework.restdocs.config.RestDocumentationConfigurer; * A REST Assured 3-specific {@link RestDocumentationConfigurer}. * * @author Andy Wilkinson + * @author Filip Hrisafov * @since 1.2.0 */ public final class RestAssuredRestDocumentationConfigurer extends - RestDocumentationConfigurer + RestDocumentationConfigurer implements Filter { private final RestAssuredSnippetConfigurer snippetConfigurer = new RestAssuredSnippetConfigurer( this); + private final RestAssuredOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = + new RestAssuredOperationPreprocessorsConfigurer(this); + private final RestDocumentationContextProvider contextProvider; RestAssuredRestDocumentationConfigurer( @@ -54,6 +59,11 @@ public final class RestAssuredRestDocumentationConfigurer extends return this.snippetConfigurer; } + @Override + public RestAssuredOperationPreprocessorsConfigurer operationPreprocessors() { + return this.operationPreprocessorsConfigurer; + } + @Override public Response filter(FilterableRequestSpecification requestSpec, FilterableResponseSpecification responseSpec, FilterContext filterContext) { 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 d1ea753d..2dc26e62 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 @@ -97,6 +97,10 @@ public class RestDocumentationFilter implements Filter { context); configuration.remove( RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS); + configuration.remove( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); + configuration.remove( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); return configuration; } diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java index caafafa5..0356cea3 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java @@ -28,6 +28,9 @@ import org.mockito.ArgumentCaptor; import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.restdocs.generate.RestDocumentationGenerator; +import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor; +import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor; +import org.springframework.restdocs.operation.preprocess.Preprocessors; import org.springframework.restdocs.snippet.WriterResolver; import org.springframework.restdocs.templates.TemplateEngine; @@ -43,6 +46,7 @@ import static org.mockito.Mockito.verify; * Tests for {@link RestAssuredRestDocumentationConfigurer}. * * @author Andy Wilkinson + * @author Filip Hrisafov */ public class RestAssuredRestDocumentationConfigurerTests { @@ -68,7 +72,11 @@ public class RestAssuredRestDocumentationConfigurerTests { @Test public void configurationIsAddedToTheContext() { - this.configurer.filter(this.requestSpec, this.responseSpec, this.filterContext); + this.configurer + .operationPreprocessors() + .withDefaultRequestPreprocessors(Preprocessors.prettyPrint()) + .withDefaultResponsePreprocessors(Preprocessors.removeHeaders("Foo")) + .filter(this.requestSpec, this.responseSpec, this.filterContext); @SuppressWarnings("rawtypes") ArgumentCaptor configurationCaptor = ArgumentCaptor.forClass(Map.class); verify(this.filterContext).setValue( @@ -84,6 +92,14 @@ public class RestAssuredRestDocumentationConfigurerTests { hasEntry( equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS), instanceOf(List.class))); + assertThat(configuration, + hasEntry( + equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR), + instanceOf(OperationRequestPreprocessor.class))); + assertThat(configuration, + hasEntry( + equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR), + instanceOf(OperationResponsePreprocessor.class))); } } 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 b71a1504..e9370351 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 @@ -71,6 +71,7 @@ import static org.springframework.restdocs.test.SnippetMatchers.snippet; * * @author Andy Wilkinson * @author Tomasz Kopczynski + * @author Filip Hrisafov */ public class RestAssuredRestDocumentationIntegrationTests { @@ -327,6 +328,31 @@ public class RestAssuredRestDocumentationIntegrationTests { .header("Host", "localhost").content(prettyPrinted)))); } + @Test + public void defaultPreprocessedRequest() throws Exception { + Pattern pattern = Pattern.compile("(\"alpha\")"); + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation) + .operationPreprocessors().withDefaultRequestPreprocessors(prettyPrint(), + replacePattern(pattern, "\"<>\""), + modifyUris().removePort(), + removeHeaders("a", HttpHeaders.CONTENT_LENGTH))) + .header("a", "alpha").header("b", "bravo").contentType("application/json") + .accept("application/json").body("{\"a\":\"alpha\"}") + .filter(document("default-preprocessed-request")) + .get("/").then().statusCode(200); + String prettyPrinted = String.format("{%n \"a\" : \"<>\"%n}"); + assertThat( + new File( + "build/generated-snippets/default-preprocessed-request/http-request.adoc"), + is(snippet(asciidoctor()) + .withContents(httpRequest(asciidoctor(), RequestMethod.GET, "/") + .header("b", "bravo") + .header("Accept", MediaType.APPLICATION_JSON_VALUE) + .header("Content-Type", "application/json; charset=UTF-8") + .header("Host", "localhost").content(prettyPrinted)))); + } + @Test public void preprocessedResponse() throws Exception { Pattern pattern = Pattern.compile("(\"alpha\")"); @@ -353,6 +379,31 @@ public class RestAssuredRestDocumentationIntegrationTests { .content(prettyPrinted)))); } + @Test + public void defaultPreprocessedResponse() throws Exception { + Pattern pattern = Pattern.compile("(\"alpha\")"); + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation) + .operationPreprocessors().withDefaultResponsePreprocessors(prettyPrint(), maskLinks(), + removeHeaders("a", "Transfer-Encoding", "Date", "Server"), + replacePattern(pattern, "\"<>\""), modifyUris() + .scheme("https").host("api.example.com").removePort())) + .filter(document("default-preprocessed-response")) + .get("/").then().statusCode(200); + String prettyPrinted = String.format("{%n \"a\" : \"<>\",%n \"links\" : " + + "[ {%n \"rel\" : \"rel\",%n \"href\" : \"...\"%n } ]%n}"); + assertThat( + new File( + "build/generated-snippets/default-preprocessed-response/http-response.adoc"), + is(snippet(asciidoctor()) + .withContents(httpResponse(asciidoctor(), HttpStatus.OK) + .header("Foo", "https://api.example.com/foo/bar") + .header("Content-Type", "application/json;charset=UTF-8") + .header(HttpHeaders.CONTENT_LENGTH, + prettyPrinted.getBytes().length) + .content(prettyPrinted)))); + } + @Test public void customSnippetTemplate() throws Exception { ClassLoader classLoader = new URLClassLoader(new URL[] { From eed90c0b9a3ba910806201bd9f3b90d7862e2cc6 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 26 Oct 2017 16:49:56 +0100 Subject: [PATCH 2/2] Polish "Add support for configuring default request and response preprocessors" Closes gh-424 --- docs/src/docs/asciidoc/configuration.adoc | 12 ++- .../customizing-requests-and-responses.adoc | 9 +- .../CustomDefaultOperationPreprocessors.java | 13 +-- .../mockmvc/EveryTestPreprocessing.java | 13 ++- .../CustomDefaultOperationPreprocessors.java | 16 ++-- .../restassured/EveryTestPreprocessing.java | 13 ++- .../OperationPreprocessorsConfigurer.java | 31 ++++--- .../config/RestDocumentationConfigurer.java | 12 +-- .../generate/RestDocumentationGenerator.java | 74 +++++++++------- .../RestDocumentationGeneratorTests.java | 88 ++++++++----------- .../RestDocumentationConfigurerTests.java | 62 ++++++++----- ...ckMvcOperationPreprocessorsConfigurer.java | 1 + .../MockMvcRestDocumentationConfigurer.java | 7 +- .../RestDocumentationResultHandler.java | 3 - ...kMvcRestDocumentationIntegrationTests.java | 11 +-- ...suredOperationPreprocessorsConfigurer.java | 10 +-- ...estAssuredRestDocumentationConfigurer.java | 7 +- ...suredRestDocumentationConfigurerTests.java | 7 +- ...uredRestDocumentationIntegrationTests.java | 28 +++--- 19 files changed, 219 insertions(+), 198 deletions(-) diff --git a/docs/src/docs/asciidoc/configuration.adoc b/docs/src/docs/asciidoc/configuration.adoc index 35490f79..1e6fca5e 100644 --- a/docs/src/docs/asciidoc/configuration.adoc +++ b/docs/src/docs/asciidoc/configuration.adoc @@ -116,21 +116,25 @@ include::{examples-dir}/com/example/restassured/CustomDefaultSnippets.java[tags= ---- [[configuration-default-preprocessors]] -=== Operation preprocessors +=== Default operation preprocessors -You can configure default Request / Response preprocessors during setup using the +You can configure default request and response preprocessors during setup using the `RestDocumentationConfigurer` API. For example, to remove the `Foo` headers from all requests and pretty print all responses: [source,java,indent=0,role="primary"] .MockMvc ---- -include::{examples-dir}/com/example/mockmvc/CustomDefaultOperationPreprocessors.java[tags=custom-default-preprocessors] +include::{examples-dir}/com/example/mockmvc/CustomDefaultOperationPreprocessors.java[tags=custom-default-operation-preprocessors] ---- +<1> Apply a request preprocessor that will remove the header named `Foo`. +<2> Apply a response preprocessor that will pretty print its content. [source,java,indent=0,role="secondary"] .REST Assured ---- -include::{examples-dir}/com/example/restassured/CustomDefaultOperationPreprocessors.java[tags=custom-default-preprocessors] +include::{examples-dir}/com/example/restassured/CustomDefaultOperationPreprocessors.java[tags=custom-default-operation-preprocessors] ---- +<1> Apply a request preprocessor that will remove the header named `Foo`. +<2> Apply a response preprocessor that will pretty print its content. diff --git a/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc b/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc index d68f7314..4cc2625b 100644 --- a/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc +++ b/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc @@ -27,20 +27,25 @@ include::{examples-dir}/com/example/restassured/PerTestPreprocessing.java[tags=p <2> Apply a response preprocessor that will pretty print its content. Alternatively, you may want to apply the same preprocessors to every test. You can do -so by configuring the preprocessors using the `RestDocumentationConfigurer` API. -For example to remove the `Foo` header from all requests and pretty print all responses: +so by configuring the preprocessors using the `RestDocumentationConfigurer` API in your +`@Before` method. For example to remove the `Foo` header from all requests and pretty print +all responses: [source,java,indent=0,role="primary"] .MockMvc ---- include::{examples-dir}/com/example/mockmvc/EveryTestPreprocessing.java[tags=setup] ---- +<1> Apply a request preprocessor that will remove the header named `Foo`. +<2> Apply a response preprocessor that will pretty print its content. [source,java,indent=0,role="secondary"] .REST Assured ---- include::{examples-dir}/com/example/restassured/EveryTestPreprocessing.java[tags=setup] ---- +<1> Apply a request preprocessor that will remove the header named `Foo`. +<2> Apply a response preprocessor that will pretty print its content. Then, in each test, any configuration specific to that test can be performed. For example: diff --git a/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java b/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java index 786c050e..c6cd2fa0 100644 --- a/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java +++ b/docs/src/test/java/com/example/mockmvc/CustomDefaultOperationPreprocessors.java @@ -35,16 +35,19 @@ public class CustomDefaultOperationPreprocessors { private WebApplicationContext context; + @SuppressWarnings("unused") private MockMvc mockMvc; @Before public void setup() { - // tag::custom-default-preprocessors[] + // tag::custom-default-operation-preprocessors[] this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(documentationConfiguration(this.restDocumentation).operationPreprocessors() - .withDefaultRequestPreprocessors(removeHeaders("Foo")) - .withDefaultResponsePreprocessors(prettyPrint())) + .apply(documentationConfiguration(this.restDocumentation) + .operationPreprocessors() + .withRequestDefaults(removeHeaders("Foo")) // <1> + .withResponseDefaults(prettyPrint())) // <2> .build(); - // end::custom-default-preprocessors[] + // end::custom-default-operation-preprocessors[] } + } diff --git a/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java b/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java index 279a3310..3b46bb21 100644 --- a/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java +++ b/docs/src/test/java/com/example/mockmvc/EveryTestPreprocessing.java @@ -45,19 +45,18 @@ public class EveryTestPreprocessing { @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(documentationConfiguration(this.restDocumentation).operationPreprocessors() - .withDefaultRequestPreprocessors(removeHeaders("Foo")) - .withDefaultResponsePreprocessors(prettyPrint())) - .build(); + .apply(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withRequestDefaults(removeHeaders("Foo")) // <1> + .withResponseDefaults(prettyPrint())) // <2> + .build(); } - // end::setup[] public void use() throws Exception { // tag::use[] - this.mockMvc.perform(get("/")) // <1> + this.mockMvc.perform(get("/")) .andExpect(status().isOk()) - .andDo(document("{method-name}", + .andDo(document("index", links(linkWithRel("self").description("Canonical self link")) )); // end::use[] diff --git a/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java b/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java index c4ebd8ff..262f9680 100644 --- a/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java +++ b/docs/src/test/java/com/example/restassured/CustomDefaultOperationPreprocessors.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2018 the original author or authors. + * Copyright 2014-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. @@ -18,7 +18,6 @@ package com.example.restassured; import io.restassured.builder.RequestSpecBuilder; import io.restassured.specification.RequestSpecification; - import org.junit.Before; import org.junit.Rule; @@ -38,12 +37,13 @@ public class CustomDefaultOperationPreprocessors { @Before public void setup() { - // tag::custom-default-preprocessors[] + // tag::custom-default-operation-preprocessors[] this.spec = new RequestSpecBuilder() - .addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors() - .withDefaultRequestPreprocessors(removeHeaders("Foo")) - .withDefaultResponsePreprocessors(prettyPrint())) - .build(); - // end::custom-default-preprocessors[] + .addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withRequestDefaults(removeHeaders("Foo")) // <1> + .withResponseDefaults(prettyPrint())) // <2> + .build(); + // end::custom-default-operation-preprocessors[] } + } diff --git a/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java b/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java index fa14f5c2..05bc3a61 100644 --- a/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java +++ b/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java @@ -43,19 +43,18 @@ public class EveryTestPreprocessing { @Before public void setup() { this.spec = new RequestSpecBuilder() - .addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors() - .withDefaultRequestPreprocessors(removeHeaders("Foo")) - .withDefaultResponsePreprocessors(prettyPrint())) - .build(); + .addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors() + .withRequestDefaults(removeHeaders("Foo")) // <1> + .withResponseDefaults(prettyPrint())) // <2> + .build(); } - // end::setup[] public void use() throws Exception { // tag::use[] RestAssured.given(this.spec) - .filter(document("{method-name]", - links(linkWithRel("self").description("Canonical self link")))) + .filter(document("index", + links(linkWithRel("self").description("Canonical self link")))) .when().get("/") .then().assertThat().statusCode(is(200)); // end::use[] diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java index afb21cc5..a0126dee 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/OperationPreprocessorsConfigurer.java @@ -26,21 +26,24 @@ import org.springframework.restdocs.operation.preprocess.OperationResponsePrepro import org.springframework.restdocs.operation.preprocess.Preprocessors; /** - * A configurer that can be used to configure the default operation preprocessors that need to be used. + * A configurer that can be used to configure the default operation preprocessors. * * @param The type of the configurer's parent * @param The concrete type of the configurer to be returned from chained methods * @author Filip Hrisafov + * @author Andy Wilkinson * @since 2.0.0 */ public abstract class OperationPreprocessorsConfigurer extends AbstractNestedConfigurer { private OperationRequestPreprocessor defaultOperationRequestPreprocessor; + private OperationResponsePreprocessor defaultOperationResponsePreprocessor; /** - * Creates a new {@code OperationPreprocessorConfigurer} with the given {@code parent}. + * Creates a new {@code OperationPreprocessorConfigurer} with the given + * {@code parent}. * * @param parent the parent */ @@ -49,34 +52,40 @@ public abstract class OperationPreprocessorsConfigurer } @Override - public void apply(Map configuration, RestDocumentationContext context) { - configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, + public void apply(Map configuration, + RestDocumentationContext context) { + configuration.put( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, this.defaultOperationRequestPreprocessor); - configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, + configuration.put( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, this.defaultOperationResponsePreprocessor); } /** - * Configures the default documentation operation request preprocessors. + * Configures the default operation request preprocessors. * * @param preprocessors the preprocessors * @return {@code this} */ @SuppressWarnings("unchecked") - public TYPE withDefaultRequestPreprocessors(OperationPreprocessor... preprocessors) { - this.defaultOperationRequestPreprocessor = Preprocessors.preprocessRequest(preprocessors); + public TYPE withRequestDefaults(OperationPreprocessor... preprocessors) { + this.defaultOperationRequestPreprocessor = Preprocessors + .preprocessRequest(preprocessors); return (TYPE) this; } /** - * Configures the default documentation operation response preprocessors. + * Configures the default operation response preprocessors. * * @param preprocessors the preprocessors * @return {@code this} */ @SuppressWarnings("unchecked") - public TYPE withDefaultResponsePreprocessors(OperationPreprocessor... preprocessors) { - this.defaultOperationResponsePreprocessor = Preprocessors.preprocessResponse(preprocessors); + public TYPE withResponseDefaults(OperationPreprocessor... preprocessors) { + this.defaultOperationResponsePreprocessor = Preprocessors + .preprocessResponse(preprocessors); return (TYPE) this; } + } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java index 75b69352..0f9c67d2 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/config/RestDocumentationConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -35,7 +35,7 @@ import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine; /** * Abstract base class for the configuration of Spring REST Docs. * - * @param The concrete type of the {@link SnippetConfigurer}. + * @param The concrete type of the {@link SnippetConfigurer} * @param

The concrete type of the {@link OperationPreprocessorsConfigurer} * @param The concrete type of this configurer, to be returned from methods that * support chaining @@ -58,8 +58,8 @@ public abstract class RestDocumentationConfigurer configuration, RestDocumentationContext context) { List configurers = Arrays.asList(snippets(), - operationPreprocessors(), - this.templateEngineConfigurer, this.writerResolverConfigurer); + operationPreprocessors(), this.templateEngineConfigurer, + this.writerResolverConfigurer); for (AbstractConfigurer configurer : configurers) { configurer.apply(configuration, context); } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java index d239ffc4..b69bae2f 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/generate/RestDocumentationGenerator.java @@ -57,17 +57,16 @@ public final class RestDocumentationGenerator { public static final String ATTRIBUTE_NAME_DEFAULT_SNIPPETS = "org.springframework.restdocs.defaultSnippets"; /** - * Name of the operation attribute used to hold the default operation request preprocessor. + * Name of the operation attribute used to hold the default operation request + * preprocessor. */ - public static final String ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR = - "org.springframework.restdocs.defaultOperationRequestPreprocessor"; + public static final String ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR = "org.springframework.restdocs.defaultOperationRequestPreprocessor"; /** - * Name of the operation attribute used to hold the default operation response preprocessor. + * Name of the operation attribute used to hold the default operation response + * preprocessor. */ - public static final String ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR = - "org.springframework.restdocs.defaultOperationResponsePreprocessor"; - + public static final String ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR = "org.springframework.restdocs.defaultOperationResponsePreprocessor"; private final String identifier; @@ -198,8 +197,10 @@ public final class RestDocumentationGenerator { */ public void handle(REQ request, RESP response, Map configuration) { Map attributes = new HashMap<>(configuration); - OperationRequest operationRequest = preprocessRequest(request, attributes); - OperationResponse operationResponse = preprocessResponse(response, attributes); + OperationRequest operationRequest = preprocessRequest( + this.requestConverter.convert(request), attributes); + OperationResponse operationResponse = preprocessResponse( + this.responseConverter.convert(response), attributes); Operation operation = new StandardOperation(this.identifier, operationRequest, operationResponse, attributes); try { @@ -239,40 +240,45 @@ public final class RestDocumentationGenerator { return combinedSnippets; } - private OperationRequest preprocessRequest(REQ request, Map configuration) { - List requestPreprocessors = getRequestPreprocessors(configuration); - OperationRequest operationRequest = this.requestConverter.convert(request); + private OperationRequest preprocessRequest(OperationRequest request, + Map configuration) { + List requestPreprocessors = getRequestPreprocessors( + configuration); for (OperationRequestPreprocessor preprocessor : requestPreprocessors) { - operationRequest = preprocessor.preprocess(operationRequest); + request = preprocessor.preprocess(request); } - return operationRequest; + return request; } - private List getRequestPreprocessors(Map configuration) { - List preprocessors = new ArrayList<>(2); - preprocessors.add(this.requestPreprocessor); - OperationRequestPreprocessor defaultRequestPreprocessor = (OperationRequestPreprocessor) configuration.get( - RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); - if (defaultRequestPreprocessor != null) { - preprocessors.add(defaultRequestPreprocessor); - } - return preprocessors; + private List getRequestPreprocessors( + Map configuration) { + return getPreprocessors(this.requestPreprocessor, + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, + configuration); } - private OperationResponse preprocessResponse(RESP response, Map configuration) { - List responsePreprocessors = getResponsePreprocessors(configuration); - OperationResponse operationResponse = this.responseConverter.convert(response); - for (OperationResponsePreprocessor preprocessor : responsePreprocessors) { - operationResponse = preprocessor.preprocess(operationResponse); + private OperationResponse preprocessResponse(OperationResponse response, + Map configuration) { + for (OperationResponsePreprocessor preprocessor : getResponsePreprocessors( + configuration)) { + response = preprocessor.preprocess(response); } - return operationResponse; + return response; } - private List getResponsePreprocessors(Map configuration) { - List preprocessors = new ArrayList<>(2); - preprocessors.add(this.responsePreprocessor); - OperationResponsePreprocessor defaultResponsePreprocessor = (OperationResponsePreprocessor) configuration.get( - RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); + private List getResponsePreprocessors( + Map configuration) { + return getPreprocessors(this.responsePreprocessor, + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, + configuration); + } + + @SuppressWarnings("unchecked") + private List getPreprocessors(T preprocessor, String preprocessorAttribute, + Map configuration) { + List preprocessors = new ArrayList<>(2); + preprocessors.add(preprocessor); + T defaultResponsePreprocessor = (T) configuration.get(preprocessorAttribute); if (defaultResponsePreprocessor != null) { preprocessors.add(defaultResponsePreprocessor); } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java index f06700a2..103a7960 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java @@ -78,8 +78,11 @@ public class RestDocumentationGeneratorTests { private final Snippet snippet = mock(Snippet.class); - private final OperationPreprocessor requestPreprocessor = mock(OperationPreprocessor.class); - private final OperationPreprocessor responsePreprocessor = mock(OperationPreprocessor.class); + private final OperationPreprocessor requestPreprocessor = mock( + OperationPreprocessor.class); + + private final OperationPreprocessor responsePreprocessor = mock( + OperationPreprocessor.class); @Test public void basicHandling() throws IOException { @@ -122,19 +125,23 @@ public class RestDocumentationGeneratorTests { HashMap configuration = new HashMap<>(); OperationPreprocessor defaultPreprocessor1 = mock(OperationPreprocessor.class); OperationPreprocessor defaultPreprocessor2 = mock(OperationPreprocessor.class); - configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, - Preprocessors.preprocessRequest(defaultPreprocessor1, defaultPreprocessor2)); + configuration.put( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, + Preprocessors.preprocessRequest(defaultPreprocessor1, + defaultPreprocessor2)); OperationRequest first = createRequest(); OperationRequest second = createRequest(); OperationRequest third = createRequest(); - given(this.requestPreprocessor.preprocess(this.operationRequest)).willReturn(first); + given(this.requestPreprocessor.preprocess(this.operationRequest)) + .willReturn(first); given(defaultPreprocessor1.preprocess(first)).willReturn(second); given(defaultPreprocessor2.preprocess(second)).willReturn(third); new RestDocumentationGenerator<>("id", this.requestConverter, - this.responseConverter, Preprocessors.preprocessRequest(this.requestPreprocessor), this.snippet) - .handle(this.request, this.response, configuration); - - verifySnippetInvocation(this.snippet, third, this.operationResponse, configuration, 1); + this.responseConverter, + Preprocessors.preprocessRequest(this.requestPreprocessor), this.snippet) + .handle(this.request, this.response, configuration); + verifySnippetInvocation(this.snippet, third, this.operationResponse, + configuration, 1); } @Test @@ -146,49 +153,24 @@ public class RestDocumentationGeneratorTests { HashMap configuration = new HashMap<>(); OperationPreprocessor defaultPreprocessor1 = mock(OperationPreprocessor.class); OperationPreprocessor defaultPreprocessor2 = mock(OperationPreprocessor.class); - configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, - Preprocessors.preprocessResponse(defaultPreprocessor1, defaultPreprocessor2)); + configuration.put( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, + Preprocessors.preprocessResponse(defaultPreprocessor1, + defaultPreprocessor2)); OperationResponse first = createResponse(); OperationResponse second = createResponse(); - OperationResponse third = new OperationResponseFactory().createFrom(this.operationResponse, new HttpHeaders()); - given(this.responsePreprocessor.preprocess(this.operationResponse)).willReturn(first); + OperationResponse third = new OperationResponseFactory() + .createFrom(this.operationResponse, new HttpHeaders()); + given(this.responsePreprocessor.preprocess(this.operationResponse)) + .willReturn(first); given(defaultPreprocessor1.preprocess(first)).willReturn(second); given(defaultPreprocessor2.preprocess(second)).willReturn(third); new RestDocumentationGenerator<>("id", this.requestConverter, - this.responseConverter, Preprocessors.preprocessResponse(this.responsePreprocessor), this.snippet) - .handle(this.request, this.response, configuration); - - verifySnippetInvocation(this.snippet, this.operationRequest, third, configuration, 1); - } - - @Test - public void defaultOperationPreprocessorsAreCalled() throws IOException { - given(this.requestConverter.convert(this.request)) - .willReturn(this.operationRequest); - given(this.responseConverter.convert(this.response)) - .willReturn(this.operationResponse); - HashMap configuration = new HashMap<>(); - OperationPreprocessor requestPreprocessor1 = mock(OperationPreprocessor.class); - configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR, - Preprocessors.preprocessRequest(requestPreprocessor1)); - OperationRequest firstRequest = createRequest(); - OperationRequest secondRequest = createRequest(); - given(this.requestPreprocessor.preprocess(this.operationRequest)).willReturn(firstRequest); - given(requestPreprocessor1.preprocess(firstRequest)).willReturn(secondRequest); - - OperationPreprocessor responsePreprocessor1 = mock(OperationPreprocessor.class); - configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR, - Preprocessors.preprocessResponse(responsePreprocessor1)); - OperationResponse firstResponse = createResponse(); - OperationResponse secondResponse = createResponse(); - given(this.responsePreprocessor.preprocess(this.operationResponse)).willReturn(firstResponse); - given(responsePreprocessor1.preprocess(firstResponse)).willReturn(secondResponse); - new RestDocumentationGenerator<>("id", this.requestConverter, - this.responseConverter, Preprocessors.preprocessRequest(this.requestPreprocessor), + this.responseConverter, Preprocessors.preprocessResponse(this.responsePreprocessor), this.snippet) - .handle(this.request, this.response, configuration); - - verifySnippetInvocation(this.snippet, secondRequest, secondResponse, configuration, 1); + .handle(this.request, this.response, configuration); + verifySnippetInvocation(this.snippet, this.operationRequest, third, configuration, + 1); } @Test @@ -225,11 +207,12 @@ public class RestDocumentationGeneratorTests { private void verifySnippetInvocation(Snippet snippet, Map attributes, int times) throws IOException { - verifySnippetInvocation(snippet, this.operationRequest, this.operationResponse, attributes, times); + verifySnippetInvocation(snippet, this.operationRequest, this.operationResponse, + attributes, times); } - private void verifySnippetInvocation(Snippet snippet, OperationRequest operationRequest, - OperationResponse operationResponse, + private void verifySnippetInvocation(Snippet snippet, + OperationRequest operationRequest, OperationResponse operationResponse, Map attributes, int times) throws IOException { ArgumentCaptor operation = ArgumentCaptor.forClass(Operation.class); verify(snippet, Mockito.times(times)).document(operation.capture()); @@ -239,13 +222,12 @@ public class RestDocumentationGeneratorTests { } private static OperationRequest createRequest() { - return new OperationRequestFactory() - .create(URI.create("http://localhost:8080"), null, null, new HttpHeaders(), null, null); + return new OperationRequestFactory().create(URI.create("http://localhost:8080"), + null, null, new HttpHeaders(), null, null); } private static OperationResponse createResponse() { - return new OperationResponseFactory() - .create(null, null, null); + return new OperationResponseFactory().create(null, null, null); } } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java index a56c5646..f8f6880c 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -16,6 +16,8 @@ package org.springframework.restdocs.config; +import java.net.URI; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,6 +25,9 @@ import java.util.Map; import org.hamcrest.Matchers; import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.restdocs.ManualRestDocumentation; import org.springframework.restdocs.RestDocumentationContext; import org.springframework.restdocs.cli.CliDocumentation; @@ -31,6 +36,10 @@ import org.springframework.restdocs.cli.HttpieRequestSnippet; import org.springframework.restdocs.generate.RestDocumentationGenerator; import org.springframework.restdocs.http.HttpRequestSnippet; import org.springframework.restdocs.http.HttpResponseSnippet; +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; +import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor; import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor; import org.springframework.restdocs.operation.preprocess.Preprocessors; @@ -94,12 +103,12 @@ public class RestDocumentationConfigurerTests { assertThat(snippetConfiguration.getTemplateFormat(), is(equalTo(TemplateFormats.asciidoctor()))); - OperationRequestPreprocessor defaultOperationRequestPreprocessor = (OperationRequestPreprocessor) - configuration.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); + OperationRequestPreprocessor defaultOperationRequestPreprocessor = (OperationRequestPreprocessor) configuration + .get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); assertThat(defaultOperationRequestPreprocessor, is(nullValue())); - OperationResponsePreprocessor defaultOperationResponsePreprocessor = (OperationResponsePreprocessor) - configuration.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); + OperationResponsePreprocessor defaultOperationResponsePreprocessor = (OperationResponsePreprocessor) configuration + .get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); assertThat(defaultOperationResponsePreprocessor, is(nullValue())); } @@ -217,26 +226,35 @@ public class RestDocumentationConfigurerTests { public void customDefaultOperationRequestPreprocessor() { Map configuration = new HashMap<>(); this.configurer.operationPreprocessors() - .withDefaultRequestPreprocessors(Preprocessors.prettyPrint(), Preprocessors.removeHeaders("Foo")) + .withRequestDefaults(Preprocessors.prettyPrint(), + Preprocessors.removeHeaders("Foo")) .apply(configuration, createContext()); - assertThat(configuration, - hasEntry( - equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR), - instanceOf(OperationRequestPreprocessor.class))); - //TODO how can we actually test that the preprocessors that we set are actually there? + OperationRequestPreprocessor preprocessor = (OperationRequestPreprocessor) configuration + .get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_REQUEST_PREPROCESSOR); + HttpHeaders headers = new HttpHeaders(); + headers.add("Foo", "value"); + OperationRequest request = new OperationRequestFactory().create( + URI.create("http://localhost:8080"), HttpMethod.GET, null, headers, null, + Collections.emptyList()); + assertThat(preprocessor.preprocess(request).getHeaders().get("Foo"), + is(nullValue())); } @Test public void customDefaultOperationResponsePreprocessor() { Map configuration = new HashMap<>(); this.configurer.operationPreprocessors() - .withDefaultResponsePreprocessors(Preprocessors.prettyPrint(), Preprocessors.removeHeaders("Foo")) + .withResponseDefaults(Preprocessors.prettyPrint(), + Preprocessors.removeHeaders("Foo")) .apply(configuration, createContext()); - assertThat(configuration, - hasEntry( - equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR), - instanceOf(OperationResponsePreprocessor.class))); - //TODO same as for the customDefaultOperationRequestPreprocessor + OperationResponsePreprocessor preprocessor = (OperationResponsePreprocessor) configuration + .get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR); + HttpHeaders headers = new HttpHeaders(); + headers.add("Foo", "value"); + OperationResponse response = new OperationResponseFactory().create(HttpStatus.OK, + headers, null); + assertThat(preprocessor.preprocess(response).getHeaders().get("Foo"), + is(nullValue())); } private RestDocumentationContext createContext() { @@ -248,14 +266,13 @@ public class RestDocumentationConfigurerTests { } private static final class TestRestDocumentationConfigurer extends - RestDocumentationConfigurer { + RestDocumentationConfigurer { private final TestSnippetConfigurer snippetConfigurer = new TestSnippetConfigurer( this); - private final TestOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = - new TestOperationPreprocessorsConfigurer(this); + private final TestOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = new TestOperationPreprocessorsConfigurer( + this); @Override public TestSnippetConfigurer snippets() { @@ -280,7 +297,8 @@ public class RestDocumentationConfigurerTests { private static final class TestOperationPreprocessorsConfigurer extends OperationPreprocessorsConfigurer { - protected TestOperationPreprocessorsConfigurer(TestRestDocumentationConfigurer parent) { + protected TestOperationPreprocessorsConfigurer( + TestRestDocumentationConfigurer parent) { super(parent); } } diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java index d41df9ed..0e5662f7 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationPreprocessorsConfigurer.java @@ -46,4 +46,5 @@ public final class MockMvcOperationPreprocessorsConfigurer extends ConfigurableMockMvcBuilder builder, WebApplicationContext context) { return and().beforeMockMvcCreated(builder, context); } + } diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java index 5606ba20..52f0231e 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationConfigurer.java @@ -37,8 +37,7 @@ import org.springframework.web.context.WebApplicationContext; * @since 1.1.0 */ public final class MockMvcRestDocumentationConfigurer extends - RestDocumentationConfigurer + RestDocumentationConfigurer implements MockMvcConfigurer { private final MockMvcSnippetConfigurer snippetConfigurer = new MockMvcSnippetConfigurer( @@ -46,8 +45,8 @@ public final class MockMvcRestDocumentationConfigurer extends private final UriConfigurer uriConfigurer = new UriConfigurer(this); - private final MockMvcOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = - new MockMvcOperationPreprocessorsConfigurer(this); + private final MockMvcOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = new MockMvcOperationPreprocessorsConfigurer( + this); private final RestDocumentationContextProvider contextManager; 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 5f255440..44904365 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 @@ -82,9 +82,6 @@ public class RestDocumentationResultHandler implements ResultHandler { .getAttribute(ATTRIBUTE_NAME_CONFIGURATION)); configuration.remove( RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS); - // TODO Do we need to remove the preprocessors here as well? - // I think that there is no test that evaluates this here. And the Javadoc does not reflect the - // behaviour getDelegate().handle(result.getRequest(), result.getResponse(), 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 0a5979b1..f76911ff 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 @@ -500,19 +500,17 @@ public class MockMvcRestDocumentationIntegrationTests { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) .apply(documentationConfiguration(this.restDocumentation) .operationPreprocessors() - .withDefaultRequestPreprocessors(prettyPrint(), + .withRequestDefaults(prettyPrint(), removeHeaders("a", HttpHeaders.HOST, HttpHeaders.CONTENT_LENGTH), replacePattern(pattern, "\"<>\""))) .build(); - MvcResult result = mockMvc .perform(get("/").header("a", "alpha").header("b", "bravo") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON).content("{\"a\":\"alpha\"}")) - .andDo(document("default-preprocessed-request")) - .andReturn(); + .andDo(document("default-preprocessed-request")).andReturn(); HttpRequestMatcher preprocessedRequest = httpRequest(asciidoctor(), RequestMethod.GET, "/"); @@ -573,12 +571,11 @@ public class MockMvcRestDocumentationIntegrationTests { Pattern pattern = Pattern.compile("(\"alpha\")"); MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) .apply(documentationConfiguration(this.restDocumentation) - .operationPreprocessors() - .withDefaultResponsePreprocessors(prettyPrint(), maskLinks(), removeHeaders("a"), + .operationPreprocessors().withResponseDefaults( + prettyPrint(), maskLinks(), removeHeaders("a"), replacePattern(pattern, "\"<>\""))) .build(); - mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(document("default-preprocessed-response")); diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java index db6cffcd..af8850a5 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredOperationPreprocessorsConfigurer.java @@ -25,18 +25,18 @@ import io.restassured.specification.FilterableResponseSpecification; import org.springframework.restdocs.config.OperationPreprocessorsConfigurer; /** - * A configurer that can be used to configure the operation preprocessors when - * using REST Assured 3. + * A configurer that can be used to configure the operation preprocessors when using REST + * Assured 3. * * @author Filip Hrisafov * @since 2.0.0 */ public final class RestAssuredOperationPreprocessorsConfigurer extends - OperationPreprocessorsConfigurer + OperationPreprocessorsConfigurer implements Filter { - RestAssuredOperationPreprocessorsConfigurer(RestAssuredRestDocumentationConfigurer parent) { + RestAssuredOperationPreprocessorsConfigurer( + RestAssuredRestDocumentationConfigurer parent) { super(parent); } diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java index b8c71fbf..807b7057 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java @@ -37,15 +37,14 @@ import org.springframework.restdocs.config.RestDocumentationConfigurer; * @since 1.2.0 */ public final class RestAssuredRestDocumentationConfigurer extends - RestDocumentationConfigurer + RestDocumentationConfigurer implements Filter { private final RestAssuredSnippetConfigurer snippetConfigurer = new RestAssuredSnippetConfigurer( this); - private final RestAssuredOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = - new RestAssuredOperationPreprocessorsConfigurer(this); + private final RestAssuredOperationPreprocessorsConfigurer operationPreprocessorsConfigurer = new RestAssuredOperationPreprocessorsConfigurer( + this); private final RestDocumentationContextProvider contextProvider; diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java index 0356cea3..250da411 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java @@ -72,10 +72,9 @@ public class RestAssuredRestDocumentationConfigurerTests { @Test public void configurationIsAddedToTheContext() { - this.configurer - .operationPreprocessors() - .withDefaultRequestPreprocessors(Preprocessors.prettyPrint()) - .withDefaultResponsePreprocessors(Preprocessors.removeHeaders("Foo")) + this.configurer.operationPreprocessors() + .withRequestDefaults(Preprocessors.prettyPrint()) + .withResponseDefaults(Preprocessors.removeHeaders("Foo")) .filter(this.requestSpec, this.responseSpec, this.filterContext); @SuppressWarnings("rawtypes") ArgumentCaptor configurationCaptor = ArgumentCaptor.forClass(Map.class); 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 e9370351..0b108bad 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 @@ -333,22 +333,24 @@ public class RestAssuredRestDocumentationIntegrationTests { Pattern pattern = Pattern.compile("(\"alpha\")"); given().port(tomcat.getPort()) .filter(documentationConfiguration(this.restDocumentation) - .operationPreprocessors().withDefaultRequestPreprocessors(prettyPrint(), - replacePattern(pattern, "\"<>\""), + .operationPreprocessors().withRequestDefaults( + prettyPrint(), replacePattern(pattern, "\"<>\""), modifyUris().removePort(), removeHeaders("a", HttpHeaders.CONTENT_LENGTH))) .header("a", "alpha").header("b", "bravo").contentType("application/json") .accept("application/json").body("{\"a\":\"alpha\"}") - .filter(document("default-preprocessed-request")) - .get("/").then().statusCode(200); + .filter(document("default-preprocessed-request")).get("/").then() + .statusCode(200); String prettyPrinted = String.format("{%n \"a\" : \"<>\"%n}"); assertThat( new File( "build/generated-snippets/default-preprocessed-request/http-request.adoc"), is(snippet(asciidoctor()) - .withContents(httpRequest(asciidoctor(), RequestMethod.GET, "/") - .header("b", "bravo") - .header("Accept", MediaType.APPLICATION_JSON_VALUE) + .withContents( + httpRequest(asciidoctor(), RequestMethod.GET, "/") + .header("b", "bravo") + .header("Accept", + MediaType.APPLICATION_JSON_VALUE) .header("Content-Type", "application/json; charset=UTF-8") .header("Host", "localhost").content(prettyPrinted)))); } @@ -384,12 +386,14 @@ public class RestAssuredRestDocumentationIntegrationTests { Pattern pattern = Pattern.compile("(\"alpha\")"); given().port(tomcat.getPort()) .filter(documentationConfiguration(this.restDocumentation) - .operationPreprocessors().withDefaultResponsePreprocessors(prettyPrint(), maskLinks(), + .operationPreprocessors() + .withResponseDefaults(prettyPrint(), maskLinks(), removeHeaders("a", "Transfer-Encoding", "Date", "Server"), - replacePattern(pattern, "\"<>\""), modifyUris() - .scheme("https").host("api.example.com").removePort())) - .filter(document("default-preprocessed-response")) - .get("/").then().statusCode(200); + replacePattern(pattern, "\"<>\""), + modifyUris().scheme("https").host("api.example.com") + .removePort())) + .filter(document("default-preprocessed-response")).get("/").then() + .statusCode(200); String prettyPrinted = String.format("{%n \"a\" : \"<>\",%n \"links\" : " + "[ {%n \"rel\" : \"rel\",%n \"href\" : \"...\"%n } ]%n}"); assertThat(