From fb01a26a16fd267f7c5de546b69358666d7fe728 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 30 Sep 2015 17:33:29 +0100 Subject: [PATCH] Allow an item to be undocumented without it causing a test failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, it was necessary to document every payload field, link, path parameter, or request. If an item was not documented a failure would occur. This has proven to be too restrictive for some use cases, for example splitting up the documentation of a payload’s fields. While it was possible to use a preprocessor to modify the operation prior to documentation to remove the items that should not be documented, this was more difficult than it needed to be. This commit adds support for marking a descriptor as ignored. Ignored descriptors count when checking that everything has been documented but do not actually appear in the generated documentation. Closes gh-143 --- .../hypermedia/HypermediaDocumentation.java | 16 ++++++ .../restdocs/hypermedia/LinkDescriptor.java | 4 +- .../restdocs/hypermedia/LinksSnippet.java | 13 +++-- .../payload/AbstractFieldsSnippet.java | 13 +++-- .../restdocs/payload/FieldDescriptor.java | 4 +- .../payload/PayloadDocumentation.java | 16 ++++++ .../request/AbstractParametersSnippet.java | 14 +++-- .../restdocs/request/ParameterDescriptor.java | 4 +- .../request/RequestDocumentation.java | 16 ++++++ .../restdocs/snippet/IgnorableDescriptor.java | 52 +++++++++++++++++++ .../hypermedia/LinksSnippetTests.java | 11 ++++ .../payload/RequestFieldsSnippetTests.java | 13 +++++ .../payload/ResponseFieldsSnippetTests.java | 13 +++++ .../request/PathParametersSnippetTests.java | 12 +++++ .../RequestParametersSnippetTests.java | 11 ++++ ...kMvcRestDocumentationIntegrationTests.java | 29 +++++++++++ 16 files changed, 226 insertions(+), 15 deletions(-) create mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/snippet/IgnorableDescriptor.java diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java index c073484e..a4fbf42d 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java @@ -51,6 +51,10 @@ public abstract class HypermediaDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a link * is documented, is not marked as optional, and is not present in the response, a * failure will also occur. + *

+ * If you do not want to document a link, a link descriptor can be marked as + * {@link LinkDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param descriptors the descriptions of the response's links * @return the snippet that will document the links @@ -70,6 +74,10 @@ public abstract class HypermediaDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a link * is documented, is not marked as optional, and is not present in the response, a * failure will also occur. + *

+ * If you do not want to document a link, a link descriptor can be marked as + * {@link LinkDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param attributes the attributes * @param descriptors the descriptions of the response's links @@ -90,6 +98,10 @@ public abstract class HypermediaDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a link * is documented, is not marked as optional, and is not present in the response, a * failure will also occur. + *

+ * If you do not want to document a link, a link descriptor can be marked as + * {@link LinkDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param linkExtractor used to extract the links from the response * @param descriptors the descriptions of the response's links @@ -110,6 +122,10 @@ public abstract class HypermediaDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a link * is documented, is not marked as optional, and is not present in the response, a * failure will also occur. + *

+ * If you do not want to document a link, a link descriptor can be marked as + * {@link LinkDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param attributes the attributes * @param linkExtractor used to extract the links from the response diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java index 810a5244..8876cf7d 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java @@ -16,7 +16,7 @@ package org.springframework.restdocs.hypermedia; -import org.springframework.restdocs.snippet.AbstractDescriptor; +import org.springframework.restdocs.snippet.IgnorableDescriptor; /** * A description of a link found in a hypermedia API. @@ -24,7 +24,7 @@ import org.springframework.restdocs.snippet.AbstractDescriptor; * @author Andy Wilkinson * @see HypermediaDocumentation#linkWithRel(String) */ -public class LinkDescriptor extends AbstractDescriptor { +public class LinkDescriptor extends IgnorableDescriptor { private final String rel; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinksSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinksSnippet.java index 8b5a04d4..79ae0ee2 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinksSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/LinksSnippet.java @@ -74,8 +74,12 @@ public class LinksSnippet extends TemplatedSnippet { super("links", attributes); this.linkExtractor = linkExtractor; for (LinkDescriptor descriptor : descriptors) { - Assert.hasText(descriptor.getRel()); - Assert.notNull(descriptor.getDescription()); + Assert.notNull(descriptor.getRel(), "Link descriptors must have a rel"); + if (!descriptor.isIgnored()) { + Assert.notNull(descriptor.getDescription(), "The descriptor for link '" + + descriptor.getRel() + "' must either have a description or be" + + " marked as " + "ignored"); + } this.descriptorsByRel.put(descriptor.getRel(), descriptor); } } @@ -131,7 +135,10 @@ public class LinksSnippet extends TemplatedSnippet { private List> createLinksModel() { List> model = new ArrayList<>(); for (Entry entry : this.descriptorsByRel.entrySet()) { - model.add(createModelForDescriptor(entry.getValue())); + LinkDescriptor descriptor = entry.getValue(); + if (!descriptor.isIgnored()) { + model.add(createModelForDescriptor(descriptor)); + } } return model; } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/AbstractFieldsSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/AbstractFieldsSnippet.java index c96b58f4..3bf98a83 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/AbstractFieldsSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/AbstractFieldsSnippet.java @@ -55,8 +55,13 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet { Map attributes) { super(type + "-fields", attributes); for (FieldDescriptor descriptor : descriptors) { - Assert.notNull(descriptor.getPath()); - Assert.notNull(descriptor.getDescription()); + Assert.notNull(descriptor.getPath(), "Field descriptors must have a path"); + if (!descriptor.isIgnored()) { + Assert.notNull(descriptor.getDescription(), "The descriptor for field '" + + descriptor.getPath() + "' must either have a description or" + + " be marked as " + "ignored"); + } + } this.fieldDescriptors = descriptors; } @@ -77,7 +82,9 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet { List> fields = new ArrayList<>(); model.put("fields", fields); for (FieldDescriptor descriptor : this.fieldDescriptors) { - fields.add(createModelForDescriptor(descriptor)); + if (!descriptor.isIgnored()) { + fields.add(createModelForDescriptor(descriptor)); + } } return model; } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldDescriptor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldDescriptor.java index 7df08f1f..d68bb68d 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldDescriptor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldDescriptor.java @@ -16,7 +16,7 @@ package org.springframework.restdocs.payload; -import org.springframework.restdocs.snippet.AbstractDescriptor; +import org.springframework.restdocs.snippet.IgnorableDescriptor; /** * A description of a field found in a request or response payload. @@ -25,7 +25,7 @@ import org.springframework.restdocs.snippet.AbstractDescriptor; * @author Andy Wilkinson * @see PayloadDocumentation#fieldWithPath(String) */ -public class FieldDescriptor extends AbstractDescriptor { +public class FieldDescriptor extends IgnorableDescriptor { private final String path; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/PayloadDocumentation.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/PayloadDocumentation.java index 56f8266f..097e1c47 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/PayloadDocumentation.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/PayloadDocumentation.java @@ -108,6 +108,10 @@ public abstract class PayloadDocumentation { * a failure will also occur. For payloads with a hierarchical structure, documenting * a field is sufficient for all of its descendants to also be treated as having been * documented. + *

+ * If you do not want to document a field, a field descriptor can be marked as + * {@link FieldDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param descriptors the descriptions of the request payload's fields * @return the snippet that will document the fields @@ -128,6 +132,10 @@ public abstract class PayloadDocumentation { * payload, a failure will also occur. For payloads with a hierarchical structure, * documenting a field is sufficient for all of its descendants to also be treated as * having been documented. + *

+ * If you do not want to document a field, a field descriptor can be marked as + * {@link FieldDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param attributes the attributes * @param descriptors the descriptions of the request payload's fields @@ -150,6 +158,10 @@ public abstract class PayloadDocumentation { * payload, a failure will also occur. For payloads with a hierarchical structure, * documenting a field is sufficient for all of its descendants to also be treated as * having been documented. + *

+ * If you do not want to document a field, a field descriptor can be marked as + * {@link FieldDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param descriptors the descriptions of the response payload's fields * @return the snippet that will document the fields @@ -170,6 +182,10 @@ public abstract class PayloadDocumentation { * payload, a failure will also occur. For payloads with a hierarchical structure, * documenting a field is sufficient for all of its descendants to also be treated as * having been documented. + *

+ * If you do not want to document a field, a field descriptor can be marked as + * {@link FieldDescriptor#ignored}. This will prevent it from appearing in the + * generated snippet while avoiding the failure described above. * * @param attributes the attributes * @param descriptors the descriptions of the response payload's fields diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippet.java index 144c8d67..0763505b 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippet.java @@ -54,8 +54,13 @@ public abstract class AbstractParametersSnippet extends TemplatedSnippet { List descriptors, Map attributes) { super(snippetName, attributes); for (ParameterDescriptor descriptor : descriptors) { - Assert.hasText(descriptor.getName()); - Assert.notNull(descriptor.getDescription()); + Assert.notNull(descriptor.getName(), "Parameter descriptors must have a name"); + if (!descriptor.isIgnored()) { + Assert.notNull(descriptor.getDescription(), + "The descriptor for parameter '" + descriptor.getName() + + "' must either have a description or be marked as " + + "ignored"); + } this.descriptorsByName.put(descriptor.getName(), descriptor); } } @@ -67,7 +72,10 @@ public abstract class AbstractParametersSnippet extends TemplatedSnippet { Map model = new HashMap<>(); List> parameters = new ArrayList<>(); for (Entry entry : this.descriptorsByName.entrySet()) { - parameters.add(createModelForDescriptor(entry.getValue())); + ParameterDescriptor descriptor = entry.getValue(); + if (!descriptor.isIgnored()) { + parameters.add(createModelForDescriptor(descriptor)); + } } model.put("parameters", parameters); return model; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/ParameterDescriptor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/ParameterDescriptor.java index ff9d561d..9172a552 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/ParameterDescriptor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/ParameterDescriptor.java @@ -16,7 +16,7 @@ package org.springframework.restdocs.request; -import org.springframework.restdocs.snippet.AbstractDescriptor; +import org.springframework.restdocs.snippet.IgnorableDescriptor; /** * A descriptor of a request or path parameter. @@ -25,7 +25,7 @@ import org.springframework.restdocs.snippet.AbstractDescriptor; * @see RequestDocumentation#parameterWithName * */ -public class ParameterDescriptor extends AbstractDescriptor { +public class ParameterDescriptor extends IgnorableDescriptor { private final String name; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/RequestDocumentation.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/RequestDocumentation.java index 61c33d5f..e0aa2f4b 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/RequestDocumentation.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/request/RequestDocumentation.java @@ -53,6 +53,10 @@ public abstract class RequestDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a * parameter is documented, is not marked as optional, and is not present in the * request path, a failure will also occur. + *

+ * If you do not want to document a path parameter, a parameter descriptor can be + * marked as {@link ParameterDescriptor#ignored}. This will prevent it from appearing + * in the generated snippet while avoiding the failure described above. * * @param descriptors the descriptions of the parameters in the request's path * @return the snippet that will document the parameters @@ -71,6 +75,10 @@ public abstract class RequestDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a * parameter is documented, is not marked as optional, and is not present in the * request path, a failure will also occur. + *

+ * If you do not want to document a path parameter, a parameter descriptor can be + * marked as {@link ParameterDescriptor#ignored}. This will prevent it from appearing + * in the generated snippet while avoiding the failure described above. * * @param attributes the attributes * @param descriptors the descriptions of the parameters in the request's path @@ -90,6 +98,10 @@ public abstract class RequestDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a * parameter is documented, is not marked as optional, and is not present in the * request, a failure will also occur. + *

+ * If you do not want to document a request parameter, a parameter descriptor can be + * marked as {@link ParameterDescriptor#ignored}. This will prevent it from appearing + * in the generated snippet while avoiding the failure described above. * * @param descriptors The descriptions of the request's parameters * @return the snippet @@ -109,6 +121,10 @@ public abstract class RequestDocumentation { * descriptors, a failure will occur when the snippet is invoked. Similarly, if a * parameter is documented, is not marked as optional, and is not present in the * request, a failure will also occur. + *

+ * If you do not want to document a request parameter, a parameter descriptor can be + * marked as {@link ParameterDescriptor#ignored}. This will prevent it from appearing + * in the generated snippet while avoiding the failure described above. * * @param attributes the attributes * @param descriptors the descriptions of the request's parameters diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/snippet/IgnorableDescriptor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/snippet/IgnorableDescriptor.java new file mode 100644 index 00000000..8174c381 --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/snippet/IgnorableDescriptor.java @@ -0,0 +1,52 @@ +/* + * Copyright 2014-2015 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.snippet; + +/** + * Base class for descriptors for items that can be ignored. + * + * @param the type of the descriptor + * @author Andy Wilkinson + */ +public abstract class IgnorableDescriptor> extends + AbstractDescriptor { + + private boolean ignored = false; + + /** + * Marks the described item as being ignored. Ignored items are not included in the + * generated documentation. + * + * @return the descriptor + */ + @SuppressWarnings("unchecked") + public final T ignored() { + this.ignored = true; + return (T) this; + } + + /** + * Returns whether or not the item being described should be ignored and, therefore, + * should not be included in the documentation. + * + * @return {@code true} if the item should be ignored, otherwise {@code false}. + */ + public final boolean isIgnored() { + return this.ignored; + } + +} diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinksSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinksSnippetTests.java index 57b9f755..cb9ac288 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinksSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinksSnippetTests.java @@ -65,6 +65,17 @@ public class LinksSnippetTests { "undocumented-link", this.snippet.getOutputDirectory()).build()); } + @Test + public void ignoredLink() throws IOException { + this.snippet.expectLinks("ignored-link").withContents( + tableWithHeader("Relation", "Description").row("b", "Link b")); + new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"), + new Link("b", "bravo")), Arrays.asList(new LinkDescriptor("a").ignored(), + new LinkDescriptor("b").description("Link b"))) + .document(new OperationBuilder("ignored-link", this.snippet + .getOutputDirectory()).build()); + } + @Test public void missingLink() throws IOException { this.thrown.expect(SnippetException.class); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/RequestFieldsSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/RequestFieldsSnippetTests.java index 1c1481c8..0fedbdee 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/RequestFieldsSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/RequestFieldsSnippetTests.java @@ -98,6 +98,19 @@ public class RequestFieldsSnippetTests { .content("{\"a\": 5}").build()); } + @Test + public void ignoredRequestField() throws IOException { + this.snippet.expectRequestFields("ignored-request-field").withContents( + tableWithHeader("Path", "Type", "Description").row("b", "Number", + "Field b")); + + new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").ignored(), + fieldWithPath("b").description("Field b"))) + .document(new OperationBuilder("ignored-request-field", this.snippet + .getOutputDirectory()).request("http://localhost") + .content("{\"a\": 5, \"b\": 4}").build()); + } + @Test public void missingRequestField() throws IOException { this.thrown.expect(SnippetException.class); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java index 56bf5688..337e6e8c 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java @@ -106,6 +106,19 @@ public class ResponseFieldsSnippetTests { .content("[\"a\", \"b\", \"c\"]").build()); } + @Test + public void ignoredResponseField() throws IOException { + this.snippet.expectResponseFields("ignored-response-field").withContents( + tableWithHeader("Path", "Type", "Description").row("b", "Number", + "Field b")); + + new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").ignored(), + fieldWithPath("b").description("Field b"))) + .document(new OperationBuilder("ignored-response-field", this.snippet + .getOutputDirectory()).response().content("{\"a\": 5, \"b\": 4}") + .build()); + } + @Test public void responseFieldsWithCustomDescriptorAttributes() throws IOException { TemplateResourceResolver resolver = mock(TemplateResourceResolver.class); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/PathParametersSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/PathParametersSnippetTests.java index f7f0f462..4f2ee0b2 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/PathParametersSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/PathParametersSnippetTests.java @@ -104,6 +104,18 @@ public class PathParametersSnippetTests { "org.springframework.restdocs.urlTemplate", "/{a}/{b}").build()); } + @Test + public void ignoredPathParameter() throws IOException { + this.snippet.expectPathParameters("ignored-path-parameter").withContents( + tableWithTitleAndHeader("/{a}/{b}", "Parameter", "Description").row("b", + "two")); + new PathParametersSnippet(Arrays.asList(parameterWithName("a").ignored(), + parameterWithName("b").description("two"))) + .document(new OperationBuilder("ignored-path-parameter", this.snippet + .getOutputDirectory()).attribute( + "org.springframework.restdocs.urlTemplate", "/{a}/{b}").build()); + } + @Test public void pathParametersWithQueryString() throws IOException { this.snippet.expectPathParameters("path-parameters-with-query-string") diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/RequestParametersSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/RequestParametersSnippetTests.java index 9ac76972..da61deec 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/RequestParametersSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/request/RequestParametersSnippetTests.java @@ -102,6 +102,17 @@ public class RequestParametersSnippetTests { .build()); } + @Test + public void ignoredRequestParameter() throws IOException { + this.snippet.expectRequestParameters("ignored-request-parameter").withContents( + tableWithHeader("Parameter", "Description").row("b", "two")); + new RequestParametersSnippet(Arrays.asList(parameterWithName("a").ignored(), + parameterWithName("b").description("two"))) + .document(new OperationBuilder("ignored-request-parameter", this.snippet + .getOutputDirectory()).request("http://localhost") + .param("a", "bravo").param("b", "bravo").build()); + } + @Test public void requestParametersWithCustomDescriptorAttributes() throws IOException { TemplateResourceResolver resolver = mock(TemplateResourceResolver.class); 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 cbf72544..8c5be89e 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 @@ -400,6 +400,30 @@ public class MockMvcRestDocumentationIntegrationTests { "$ curl 'http://localhost:8080/custom/' -i -H 'Accept: application/json'")))); } + @Test + public void stackOverflowQuestion() throws Exception { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation)).build(); + + mockMvc.perform(get("/company/5").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document( + "company", + responseFields( + fieldWithPath("companyName").description( + "The name of the company"), + fieldWithPath("employee").description( + "An array of the company's employees")))) + .andDo(document( + "employee", + responseFields( + fieldWithPath("companyName").ignored(), + fieldWithPath("employee[].name").description( + "The name of the employee"), + fieldWithPath("employee[].age").description( + "The age of the employee")))); + } + private void assertExpectedSnippetFilesExist(File directory, String... snippets) { for (String snippet : snippets) { assertTrue(new File(directory, snippet).isFile()); @@ -434,6 +458,11 @@ public class MockMvcRestDocumentationIntegrationTests { HttpStatus.OK); } + @RequestMapping(value = "/company/5", produces = MediaType.APPLICATION_JSON_VALUE) + public String bar() { + return "{\"companyName\": \"FooBar\",\"employee\": [{\"name\": \"Lorem\",\"age\": \"42\"},{\"name\": \"Ipsum\",\"age\": \"24\"}]}"; + } + } }