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 a27f258d..a721ee65 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 @@ -153,7 +153,8 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet { if (this.subsectionExtractor != null) { content = verifyContent(this.subsectionExtractor.extractSubsection(content, contentType)); } - ContentHandler contentHandler = ContentHandler.forContent(content, contentType); + ContentHandler contentHandler = ContentHandler.forContentWithDescriptors(content, contentType, + this.fieldDescriptors); validateFieldDocumentation(contentHandler); @@ -193,10 +194,9 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet { } private void validateFieldDocumentation(ContentHandler payloadHandler) { - List missingFields = payloadHandler.findMissingFields(this.fieldDescriptors); + List missingFields = payloadHandler.findMissingFields(); - String undocumentedPayload = this.ignoreUndocumentedFields ? null - : payloadHandler.getUndocumentedContent(this.fieldDescriptors); + String undocumentedPayload = this.ignoreUndocumentedFields ? null : payloadHandler.getUndocumentedContent(); if (!missingFields.isEmpty() || StringUtils.hasText(undocumentedPayload)) { String message = ""; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/ContentHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/ContentHandler.java index 417ed965..0111548c 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/ContentHandler.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/ContentHandler.java @@ -30,41 +30,40 @@ interface ContentHandler extends FieldTypeResolver { /** * Finds the fields that are missing from the handler's payload. A field is missing if - * it is described by one of the {@code fieldDescriptors} but is not present in the - * payload. - * @param fieldDescriptors the descriptors + * it is described but is not present in the payload. * @return descriptors for the fields that are missing from the payload * @throws PayloadHandlingException if a failure occurs */ - List findMissingFields(List fieldDescriptors); + List findMissingFields(); /** * Returns modified content, formatted as a String, that only contains the fields that * are undocumented. A field is undocumented if it is present in the handler's content - * but is not described by the given {@code fieldDescriptors}. If the content is - * completely documented, {@code null} is returned - * @param fieldDescriptors the descriptors + * but is not described. If the content is completely documented, {@code null} is + * returned * @return the undocumented content, or {@code null} if all of the content is * documented * @throws PayloadHandlingException if a failure occurs */ - String getUndocumentedContent(List fieldDescriptors); + String getUndocumentedContent(); /** - * Create a {@link ContentHandler} for the given content type and payload. + * Create a {@link ContentHandler} for the given content type and payload, described + * by the given descriptors. * @param content the payload * @param contentType the content type + * @param descriptors descriptors of the content * @return the ContentHandler * @throws PayloadHandlingException if no known ContentHandler can handle the content */ - static ContentHandler forContent(byte[] content, MediaType contentType) { - + static ContentHandler forContentWithDescriptors(byte[] content, MediaType contentType, + List descriptors) { try { - return new JsonContentHandler(content); + return new JsonContentHandler(content, descriptors); } catch (Exception je) { try { - return new XmlContentHandler(content); + return new XmlContentHandler(content, descriptors); } catch (Exception xe) { throw new PayloadHandlingException( diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldTypeResolver.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldTypeResolver.java index 530a2a07..6c8397c3 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldTypeResolver.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldTypeResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2018 the original author or authors. + * Copyright 2014-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.restdocs.payload; +import java.util.Collections; +import java.util.List; + import org.springframework.http.MediaType; /** @@ -33,9 +36,25 @@ public interface FieldTypeResolver { * @param content the payload that the {@code FieldTypeResolver} should handle * @param contentType the content type of the payload * @return the {@code FieldTypeResolver} + * @deprecated since 2.0.4 in favor of + * {@link #forContentWithDescriptors(byte[], MediaType, List)} */ + @Deprecated static FieldTypeResolver forContent(byte[] content, MediaType contentType) { - return ContentHandler.forContent(content, contentType); + return forContentWithDescriptors(content, contentType, Collections.emptyList()); + } + + /** + * Create a {@code FieldTypeResolver} for the given {@code content} and + * {@code contentType}, described by the given {@code descriptors}. + * @param content the payload that the {@code FieldTypeResolver} should handle + * @param contentType the content type of the payload + * @param descriptors the descriptors of the content + * @return the {@code FieldTypeResolver} + */ + static FieldTypeResolver forContentWithDescriptors(byte[] content, MediaType contentType, + List descriptors) { + return ContentHandler.forContentWithDescriptors(content, contentType, descriptors); } /** diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonContentHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonContentHandler.java index a5829276..976a2771 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonContentHandler.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonContentHandler.java @@ -44,18 +44,21 @@ class JsonContentHandler implements ContentHandler { private final byte[] rawContent; - JsonContentHandler(byte[] content) { + private final List fieldDescriptors; + + JsonContentHandler(byte[] content, List fieldDescriptors) { this.rawContent = content; + this.fieldDescriptors = fieldDescriptors; readContent(); } @Override - public List findMissingFields(List fieldDescriptors) { + public List findMissingFields() { List missingFields = new ArrayList<>(); Object payload = readContent(); - for (FieldDescriptor fieldDescriptor : fieldDescriptors) { + for (FieldDescriptor fieldDescriptor : this.fieldDescriptors) { if (!fieldDescriptor.isOptional() && !this.fieldProcessor.hasField(fieldDescriptor.getPath(), payload) - && !isNestedBeneathMissingOptionalField(fieldDescriptor, fieldDescriptors, payload)) { + && !isNestedBeneathMissingOptionalField(fieldDescriptor, payload)) { missingFields.add(fieldDescriptor); } } @@ -63,9 +66,8 @@ class JsonContentHandler implements ContentHandler { return missingFields; } - private boolean isNestedBeneathMissingOptionalField(FieldDescriptor missing, List fieldDescriptors, - Object payload) { - List candidates = new ArrayList<>(fieldDescriptors); + private boolean isNestedBeneathMissingOptionalField(FieldDescriptor missing, Object payload) { + List candidates = new ArrayList<>(this.fieldDescriptors); candidates.remove(missing); for (FieldDescriptor candidate : candidates) { if (candidate.isOptional() && missing.getPath().startsWith(candidate.getPath()) @@ -98,9 +100,9 @@ class JsonContentHandler implements ContentHandler { } @Override - public String getUndocumentedContent(List fieldDescriptors) { + public String getUndocumentedContent() { Object content = readContent(); - for (FieldDescriptor fieldDescriptor : fieldDescriptors) { + for (FieldDescriptor fieldDescriptor : this.fieldDescriptors) { if (describesSubsection(fieldDescriptor)) { this.fieldProcessor.removeSubsection(fieldDescriptor.getPath(), content); } @@ -154,7 +156,9 @@ class JsonContentHandler implements ContentHandler { .discoverFieldTypes(fieldDescriptor.getPath(), readContent()) .coalesce(fieldDescriptor.isOptional()); if (descriptorFieldType == JsonFieldType.VARIES || descriptorFieldType == actualFieldType - || (fieldDescriptor.isOptional() && actualFieldType == JsonFieldType.NULL)) { + || (fieldDescriptor.isOptional() && actualFieldType == JsonFieldType.NULL) + || (isNestedBeneathMissingOptionalField(fieldDescriptor, readContent()) + && actualFieldType == JsonFieldType.VARIES)) { return descriptorFieldType; } throw new FieldTypesDoNotMatchException(fieldDescriptor, actualFieldType); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java index 6f58ac1e..8ca81990 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java @@ -53,7 +53,9 @@ class XmlContentHandler implements ContentHandler { private final byte[] rawContent; - XmlContentHandler(byte[] rawContent) { + private final List fieldDescriptors; + + XmlContentHandler(byte[] rawContent, List fieldDescriptors) { try { this.documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } @@ -61,14 +63,15 @@ class XmlContentHandler implements ContentHandler { throw new IllegalStateException("Failed to create document builder", ex); } this.rawContent = rawContent; + this.fieldDescriptors = fieldDescriptors; readPayload(); } @Override - public List findMissingFields(List fieldDescriptors) { + public List findMissingFields() { List missingFields = new ArrayList<>(); Document payload = readPayload(); - for (FieldDescriptor fieldDescriptor : fieldDescriptors) { + for (FieldDescriptor fieldDescriptor : this.fieldDescriptors) { if (!fieldDescriptor.isOptional()) { NodeList matchingNodes = findMatchingNodes(fieldDescriptor, payload); if (matchingNodes.getLength() == 0) { @@ -103,10 +106,10 @@ class XmlContentHandler implements ContentHandler { } @Override - public String getUndocumentedContent(List fieldDescriptors) { + public String getUndocumentedContent() { Document payload = readPayload(); List matchedButNotRemoved = new ArrayList<>(); - for (FieldDescriptor fieldDescriptor : fieldDescriptors) { + for (FieldDescriptor fieldDescriptor : this.fieldDescriptors) { NodeList matchingNodes; try { matchingNodes = (NodeList) createXPath(fieldDescriptor.getPath()).evaluate(payload, diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldTypeResolverTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldTypeResolverTests.java index fa96e92e..17d3edf5 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldTypeResolverTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldTypeResolverTests.java @@ -16,6 +16,8 @@ package org.springframework.restdocs.payload; +import java.util.Collections; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -35,21 +37,43 @@ public class FieldTypeResolverTests { public ExpectedException thrownException = ExpectedException.none(); @Test - public void returnJsonFieldTypeResolver() { + @Deprecated + public void whenForContentCalledWithJsonContentThenReturnsJsonFieldTypeResolver() { assertThat(FieldTypeResolver.forContent("{\"field\": \"value\"}".getBytes(), MediaType.APPLICATION_JSON)) .isInstanceOf(JsonContentHandler.class); } @Test - public void returnXmlContentHandler() { + @Deprecated + public void whenForContentCalledWithXmlContentThenReturnsXmlContentHandler() { assertThat(FieldTypeResolver.forContent("5".getBytes(), MediaType.APPLICATION_XML)) .isInstanceOf(XmlContentHandler.class); } @Test - public void throwOnInvalidContent() { + @Deprecated + public void whenForContentIsCalledWithInvalidContentThenExceptionIsThrown() { this.thrownException.expect(PayloadHandlingException.class); FieldTypeResolver.forContent("some".getBytes(), MediaType.APPLICATION_XML); } + @Test + public void whenForContentWithDescriptorsCalledWithJsonContentThenReturnsJsonFieldTypeResolver() { + assertThat(FieldTypeResolver.forContentWithDescriptors("{\"field\": \"value\"}".getBytes(), + MediaType.APPLICATION_JSON, Collections.emptyList())).isInstanceOf(JsonContentHandler.class); + } + + @Test + public void whenForContentWithDescriptorsCalledWithXmlContentThenReturnsXmlContentHandler() { + assertThat(FieldTypeResolver.forContentWithDescriptors("5".getBytes(), MediaType.APPLICATION_XML, + Collections.emptyList())).isInstanceOf(XmlContentHandler.class); + } + + @Test + public void whenForContentWithDescriptorsIsCalledWithInvalidContentThenExceptionIsThrown() { + this.thrownException.expect(PayloadHandlingException.class); + FieldTypeResolver.forContentWithDescriptors("some".getBytes(), MediaType.APPLICATION_XML, + Collections.emptyList()); + } + } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonContentHandlerTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonContentHandlerTests.java index 1055a720..6785bcac 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonContentHandlerTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonContentHandlerTests.java @@ -16,7 +16,9 @@ package org.springframework.restdocs.payload; +import java.io.IOException; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Rule; @@ -39,137 +41,163 @@ public class JsonContentHandlerTests { @Test public void typeForFieldWithNullValueMustMatch() { this.thrown.expect(FieldTypesDoNotMatchException.class); - new JsonContentHandler("{\"a\": null}".getBytes()) - .resolveFieldType(new FieldDescriptor("a").type(JsonFieldType.STRING)); + FieldDescriptor descriptor = new FieldDescriptor("a").type(JsonFieldType.STRING); + new JsonContentHandler("{\"a\": null}".getBytes(), Arrays.asList(descriptor)).resolveFieldType(descriptor); } @Test public void typeForFieldWithNotNullAndThenNullValueMustMatch() { this.thrown.expect(FieldTypesDoNotMatchException.class); - new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}".getBytes()) - .resolveFieldType(new FieldDescriptor("a[].id").type(JsonFieldType.STRING)); + FieldDescriptor descriptor = new FieldDescriptor("a[].id").type(JsonFieldType.STRING); + new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}".getBytes(), Arrays.asList(descriptor)) + .resolveFieldType(descriptor); } @Test public void typeForFieldWithNullAndThenNotNullValueMustMatch() { this.thrown.expect(FieldTypesDoNotMatchException.class); - new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes()) - .resolveFieldType(new FieldDescriptor("a.[].id").type(JsonFieldType.STRING)); + FieldDescriptor descriptor = new FieldDescriptor("a.[].id").type(JsonFieldType.STRING); + new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes(), Arrays.asList(descriptor)) + .resolveFieldType(descriptor); } @Test public void typeForOptionalFieldWithNumberAndThenNullValueIsNumber() { - Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes()) - .resolveFieldType(new FieldDescriptor("a[].id").optional()); + FieldDescriptor descriptor = new FieldDescriptor("a[].id").optional(); + Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes(), + Arrays.asList(descriptor)).resolveFieldType(descriptor); assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.NUMBER); } @Test public void typeForOptionalFieldWithNullAndThenNumberIsNumber() { - Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes()) - .resolveFieldType(new FieldDescriptor("a[].id").optional()); + FieldDescriptor descriptor = new FieldDescriptor("a[].id").optional(); + Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes(), + Arrays.asList(descriptor)).resolveFieldType(descriptor); assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.NUMBER); } @Test public void typeForFieldWithNumberAndThenNullValueIsVaries() { - Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes()) - .resolveFieldType(new FieldDescriptor("a[].id")); + FieldDescriptor descriptor = new FieldDescriptor("a[].id"); + Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes(), + Arrays.asList(descriptor)).resolveFieldType(descriptor); assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.VARIES); } @Test public void typeForFieldWithNullAndThenNumberIsVaries() { - Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes()) - .resolveFieldType(new FieldDescriptor("a[].id")); + FieldDescriptor descriptor = new FieldDescriptor("a[].id"); + Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes(), + Arrays.asList(descriptor)).resolveFieldType(descriptor); assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.VARIES); } @Test public void typeForOptionalFieldWithNullValueCanBeProvidedExplicitly() { - Object fieldType = new JsonContentHandler("{\"a\": null}".getBytes()) - .resolveFieldType(new FieldDescriptor("a").type(JsonFieldType.STRING).optional()); + FieldDescriptor descriptor = new FieldDescriptor("a").type(JsonFieldType.STRING).optional(); + Object fieldType = new JsonContentHandler("{\"a\": null}".getBytes(), Arrays.asList(descriptor)) + .resolveFieldType(descriptor); assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.STRING); } + @Test + public void typeForFieldWithSometimesPresentOptionalAncestorCanBeProvidedExplicitly() throws IOException { + FieldDescriptor descriptor = new FieldDescriptor("a.[].b.c").type(JsonFieldType.NUMBER); + FieldDescriptor ancestor = new FieldDescriptor("a.[].b").optional(); + Object fieldType = new JsonContentHandler("{\"a\":[ { \"d\": 4}, {\"b\":{\"c\":5}, \"d\": 4}]}".getBytes(), + Arrays.asList(descriptor, ancestor)).resolveFieldType(descriptor); + assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.NUMBER); + } + @Test public void failsFastWithNonJsonContent() { this.thrown.expect(PayloadHandlingException.class); - new JsonContentHandler("Non-JSON content".getBytes()); + new JsonContentHandler("Non-JSON content".getBytes(), Collections.emptyList()); } @Test public void describedFieldThatIsNotPresentIsConsideredMissing() { - List missingFields = new JsonContentHandler("{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes()) - .findMissingFields( - Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"), new FieldDescriptor("c"))); + List descriptors = Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"), + new FieldDescriptor("c")); + List missingFields = new JsonContentHandler("{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes(), + descriptors).findMissingFields(); assertThat(missingFields.size()).isEqualTo(1); assertThat(missingFields.get(0).getPath()).isEqualTo("c"); } @Test public void describedOptionalFieldThatIsNotPresentIsNotConsideredMissing() { - List missingFields = new JsonContentHandler("{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"), - new FieldDescriptor("c").optional())); + List descriptors = Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"), + new FieldDescriptor("c").optional()); + List missingFields = new JsonContentHandler("{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes(), + descriptors).findMissingFields(); assertThat(missingFields.size()).isEqualTo(0); } @Test public void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsPresentIsConsideredMissing() { - List missingFields = new JsonContentHandler("{\"a\":\"alpha\",\"b\":\"bravo\"}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("b"), - new FieldDescriptor("a.c"))); + List descriptors = Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("b"), + new FieldDescriptor("a.c")); + List missingFields = new JsonContentHandler("{\"a\":\"alpha\",\"b\":\"bravo\"}".getBytes(), + descriptors).findMissingFields(); assertThat(missingFields.size()).isEqualTo(1); assertThat(missingFields.get(0).getPath()).isEqualTo("a.c"); } @Test public void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsNotPresentIsNotConsideredMissing() { - List missingFields = new JsonContentHandler("{\"b\":\"bravo\"}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("b"), - new FieldDescriptor("a.c"))); + List descriptors = Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("b"), + new FieldDescriptor("a.c")); + List missingFields = new JsonContentHandler("{\"b\":\"bravo\"}".getBytes(), descriptors) + .findMissingFields(); assertThat(missingFields.size()).isEqualTo(0); } @Test public void describedFieldThatIsNotPresentNestedBeneathOptionalArrayThatIsEmptyIsNotConsideredMissing() { - List missingFields = new JsonContentHandler("{\"outer\":[]}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("outer"), - new FieldDescriptor("outer[]").optional(), new FieldDescriptor("outer[].inner"))); + List descriptors = Arrays.asList(new FieldDescriptor("outer"), + new FieldDescriptor("outer[]").optional(), new FieldDescriptor("outer[].inner")); + List missingFields = new JsonContentHandler("{\"outer\":[]}".getBytes(), descriptors) + .findMissingFields(); assertThat(missingFields.size()).isEqualTo(0); } @Test public void describedSometimesPresentFieldThatIsChildOfSometimesPresentOptionalArrayIsNotConsideredMissing() { + List descriptors = Arrays.asList(new FieldDescriptor("a.[].c").optional(), + new FieldDescriptor("a.[].c.d")); List missingFields = new JsonContentHandler( - "{\"a\":[ {\"b\": \"bravo\"}, {\"b\": \"bravo\", \"c\": { \"d\": \"delta\"}}]}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a.[].c").optional(), - new FieldDescriptor("a.[].c.d"))); + "{\"a\":[ {\"b\": \"bravo\"}, {\"b\": \"bravo\", \"c\": { \"d\": \"delta\"}}]}".getBytes(), descriptors) + .findMissingFields(); assertThat(missingFields.size()).isEqualTo(0); } @Test public void describedMissingFieldThatIsChildOfNestedOptionalArrayThatIsEmptyIsNotConsideredMissing() { - List missingFields = new JsonContentHandler("{\"a\":[{\"b\":[]}]}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a.[].b").optional(), - new FieldDescriptor("a.[].b.[]").optional(), new FieldDescriptor("a.[].b.[].c"))); + List descriptors = Arrays.asList(new FieldDescriptor("a.[].b").optional(), + new FieldDescriptor("a.[].b.[]").optional(), new FieldDescriptor("a.[].b.[].c")); + List missingFields = new JsonContentHandler("{\"a\":[{\"b\":[]}]}".getBytes(), descriptors) + .findMissingFields(); assertThat(missingFields.size()).isEqualTo(0); } @Test public void describedMissingFieldThatIsChildOfNestedOptionalArrayThatContainsAnObjectIsConsideredMissing() { - List missingFields = new JsonContentHandler("{\"a\":[{\"b\":[{}]}]}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a.[].b").optional(), - new FieldDescriptor("a.[].b.[]").optional(), new FieldDescriptor("a.[].b.[].c"))); + List descriptors = Arrays.asList(new FieldDescriptor("a.[].b").optional(), + new FieldDescriptor("a.[].b.[]").optional(), new FieldDescriptor("a.[].b.[].c")); + List missingFields = new JsonContentHandler("{\"a\":[{\"b\":[{}]}]}".getBytes(), descriptors) + .findMissingFields(); assertThat(missingFields.size()).isEqualTo(1); assertThat(missingFields.get(0).getPath()).isEqualTo("a.[].b.[].c"); } @Test public void describedMissingFieldThatIsChildOfOptionalObjectThatIsNullIsNotConsideredMissing() { - List missingFields = new JsonContentHandler("{\"a\":null}".getBytes()) - .findMissingFields(Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("a.b"))); + List descriptors = Arrays.asList(new FieldDescriptor("a").optional(), + new FieldDescriptor("a.b")); + List missingFields = new JsonContentHandler("{\"a\":null}".getBytes(), descriptors) + .findMissingFields(); assertThat(missingFields.size()).isEqualTo(0); } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/XmlContentHandlerTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/XmlContentHandlerTests.java index 240107f6..24b1f8b2 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/XmlContentHandlerTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/XmlContentHandlerTests.java @@ -17,6 +17,8 @@ package org.springframework.restdocs.payload; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.junit.Rule; import org.junit.Test; @@ -38,56 +40,56 @@ public class XmlContentHandlerTests { @Test public void topLevelElementCanBeDocumented() { - String undocumentedContent = createHandler("5") - .getUndocumentedContent(Arrays.asList(fieldWithPath("a").type("a").description("description"))); + List descriptors = Arrays.asList(fieldWithPath("a").type("a").description("description")); + String undocumentedContent = createHandler("5", descriptors).getUndocumentedContent(); assertThat(undocumentedContent).isNull(); } @Test public void nestedElementCanBeDocumentedLeavingAncestors() { - String undocumentedContent = createHandler("5") - .getUndocumentedContent(Arrays.asList(fieldWithPath("a/b").type("b").description("description"))); + List descriptors = Arrays.asList(fieldWithPath("a/b").type("b").description("description")); + String undocumentedContent = createHandler("5", descriptors).getUndocumentedContent(); assertThat(undocumentedContent).isEqualTo(String.format("%n")); } @Test public void fieldDescriptorDoesNotDocumentEntireSubsection() { - String undocumentedContent = createHandler("5") - .getUndocumentedContent(Arrays.asList(fieldWithPath("a").type("a").description("description"))); + List descriptors = Arrays.asList(fieldWithPath("a").type("a").description("description")); + String undocumentedContent = createHandler("5", descriptors).getUndocumentedContent(); assertThat(undocumentedContent).isEqualTo(String.format("%n 5%n%n")); } @Test public void subsectionDescriptorDocumentsEntireSubsection() { - String undocumentedContent = createHandler("5") - .getUndocumentedContent(Arrays.asList(subsectionWithPath("a").type("a").description("description"))); + List descriptors = Arrays.asList(subsectionWithPath("a").type("a").description("description")); + String undocumentedContent = createHandler("5", descriptors).getUndocumentedContent(); assertThat(undocumentedContent).isNull(); } @Test public void multipleElementsCanBeInDescendingOrderDocumented() { - String undocumentedContent = createHandler("5") - .getUndocumentedContent(Arrays.asList(fieldWithPath("a").type("a").description("description"), - fieldWithPath("a/b").type("b").description("description"))); + List descriptors = Arrays.asList(fieldWithPath("a").type("a").description("description"), + fieldWithPath("a/b").type("b").description("description")); + String undocumentedContent = createHandler("5", descriptors).getUndocumentedContent(); assertThat(undocumentedContent).isNull(); } @Test public void multipleElementsCanBeInAscendingOrderDocumented() { - String undocumentedContent = createHandler("5") - .getUndocumentedContent(Arrays.asList(fieldWithPath("a/b").type("b").description("description"), - fieldWithPath("a").type("a").description("description"))); + List descriptors = Arrays.asList(fieldWithPath("a/b").type("b").description("description"), + fieldWithPath("a").type("a").description("description")); + String undocumentedContent = createHandler("5", descriptors).getUndocumentedContent(); assertThat(undocumentedContent).isNull(); } @Test public void failsFastWithNonXmlContent() { this.thrown.expect(PayloadHandlingException.class); - createHandler("non-XML content"); + createHandler("non-XML content", Collections.emptyList()); } - private XmlContentHandler createHandler(String xml) { - return new XmlContentHandler(xml.getBytes()); + private XmlContentHandler createHandler(String xml, List descriptors) { + return new XmlContentHandler(xml.getBytes(), descriptors); } }