Merge pull request #549 from Mathias Düsterhöft
* gh-549: Polish "Provide a public API for resolving the type of a field" Provide a public API for resolving the type of a field Rework JsonFieldTypeResolver to only discover the field types
This commit is contained in:
@@ -38,6 +38,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Andreas Evers
|
||||
* @author Andy Wilkinson
|
||||
* @author Mathias Düsterhöft
|
||||
*/
|
||||
public abstract class AbstractFieldsSnippet extends TemplatedSnippet {
|
||||
|
||||
@@ -160,7 +161,7 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet {
|
||||
content = verifyContent(
|
||||
this.subsectionExtractor.extractSubsection(content, contentType));
|
||||
}
|
||||
ContentHandler contentHandler = getContentHandler(content, contentType);
|
||||
ContentHandler contentHandler = ContentHandler.forContent(content, contentType);
|
||||
|
||||
validateFieldDocumentation(contentHandler);
|
||||
|
||||
@@ -168,7 +169,7 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet {
|
||||
for (FieldDescriptor descriptor : this.fieldDescriptors) {
|
||||
if (!descriptor.isIgnored()) {
|
||||
try {
|
||||
Object type = contentHandler.determineFieldType(descriptor);
|
||||
Object type = contentHandler.resolveFieldType(descriptor);
|
||||
descriptorsToDocument.add(copyWithType(descriptor, type));
|
||||
}
|
||||
catch (FieldDoesNotExistException ex) {
|
||||
@@ -200,36 +201,6 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet {
|
||||
return content;
|
||||
}
|
||||
|
||||
private ContentHandler getContentHandler(byte[] content, MediaType contentType) {
|
||||
ContentHandler contentHandler = createJsonContentHandler(content);
|
||||
if (contentHandler == null) {
|
||||
contentHandler = createXmlContentHandler(content);
|
||||
if (contentHandler == null) {
|
||||
throw new PayloadHandlingException("Cannot handle " + contentType
|
||||
+ " content as it could not be parsed as JSON or XML");
|
||||
}
|
||||
}
|
||||
return contentHandler;
|
||||
}
|
||||
|
||||
private ContentHandler createJsonContentHandler(byte[] content) {
|
||||
try {
|
||||
return new JsonContentHandler(content);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ContentHandler createXmlContentHandler(byte[] content) {
|
||||
try {
|
||||
return new XmlContentHandler(content);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateFieldDocumentation(ContentHandler payloadHandler) {
|
||||
List<FieldDescriptor> missingFields = payloadHandler
|
||||
.findMissingFields(this.fieldDescriptors);
|
||||
|
||||
@@ -18,12 +18,15 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* A handler for the content of a request or response.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Mathias Düsterhöft
|
||||
*/
|
||||
interface ContentHandler {
|
||||
interface ContentHandler extends FieldTypeResolver {
|
||||
|
||||
/**
|
||||
* Finds the fields that are missing from the handler's payload. A field is missing if
|
||||
@@ -48,11 +51,26 @@ interface ContentHandler {
|
||||
String getUndocumentedContent(List<FieldDescriptor> fieldDescriptors);
|
||||
|
||||
/**
|
||||
* Returns the type of the field that is described by the given
|
||||
* {@code fieldDescriptor} based on the content of the payload.
|
||||
* @param fieldDescriptor the field descriptor
|
||||
* @return the type of the field
|
||||
* Create a {@link ContentHandler} for the given content type and payload.
|
||||
* @param content the payload
|
||||
* @param contentType the content type
|
||||
* @return the ContentHandler
|
||||
* @throws PayloadHandlingException if no known ContentHandler can handle the content
|
||||
*/
|
||||
Object determineFieldType(FieldDescriptor fieldDescriptor);
|
||||
static ContentHandler forContent(byte[] content, MediaType contentType) {
|
||||
|
||||
try {
|
||||
return new JsonContentHandler(content);
|
||||
}
|
||||
catch (Exception je) {
|
||||
try {
|
||||
return new XmlContentHandler(content);
|
||||
}
|
||||
catch (Exception xe) {
|
||||
throw new PayloadHandlingException("Cannot handle " + contentType
|
||||
+ " content as it could not be parsed as JSON or XML");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 org.springframework.restdocs.payload;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Resolves the type of a field in a request or response payload.
|
||||
*
|
||||
* @author Mathias Düsterhöft
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public interface FieldTypeResolver {
|
||||
|
||||
/**
|
||||
* Create a {@code FieldTypeResolver} for the given {@code content} and
|
||||
* {@code contentType}.
|
||||
* @param content the payload that the {@code FieldTypeResolver} should handle
|
||||
* @param contentType the content type of the payload
|
||||
* @return the {@code FieldTypeResolver}
|
||||
*/
|
||||
static FieldTypeResolver forContent(byte[] content, MediaType contentType) {
|
||||
return ContentHandler.forContent(content, contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the type of the field that is described by the given
|
||||
* {@code fieldDescriptor} based on the content of the payload.
|
||||
* @param fieldDescriptor the field descriptor
|
||||
* @return the type of the field
|
||||
*/
|
||||
Object resolveFieldType(FieldDescriptor fieldDescriptor);
|
||||
|
||||
}
|
||||
@@ -32,12 +32,13 @@ import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
|
||||
* A {@link ContentHandler} for JSON content.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Mathias Düsterhöft
|
||||
*/
|
||||
class JsonContentHandler implements ContentHandler {
|
||||
|
||||
private final JsonFieldProcessor fieldProcessor = new JsonFieldProcessor();
|
||||
|
||||
private final JsonFieldTypeResolver fieldTypeResolver = new JsonFieldTypeResolver();
|
||||
private final JsonFieldTypesDiscoverer fieldTypesDiscoverer = new JsonFieldTypesDiscoverer();
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
@@ -145,18 +146,20 @@ class JsonContentHandler implements ContentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object determineFieldType(FieldDescriptor fieldDescriptor) {
|
||||
public Object resolveFieldType(FieldDescriptor fieldDescriptor) {
|
||||
if (fieldDescriptor.getType() == null) {
|
||||
return this.fieldTypeResolver.resolveFieldType(fieldDescriptor,
|
||||
readContent());
|
||||
return this.fieldTypesDiscoverer
|
||||
.discoverFieldTypes(fieldDescriptor.getPath(), readContent())
|
||||
.coalesce(fieldDescriptor.isOptional());
|
||||
}
|
||||
if (!(fieldDescriptor.getType() instanceof JsonFieldType)) {
|
||||
return fieldDescriptor.getType();
|
||||
}
|
||||
JsonFieldType descriptorFieldType = (JsonFieldType) fieldDescriptor.getType();
|
||||
try {
|
||||
JsonFieldType actualFieldType = this.fieldTypeResolver
|
||||
.resolveFieldType(fieldDescriptor, readContent());
|
||||
JsonFieldType actualFieldType = this.fieldTypesDiscoverer
|
||||
.discoverFieldTypes(fieldDescriptor.getPath(), readContent())
|
||||
.coalesce(fieldDescriptor.isOptional());
|
||||
if (descriptorFieldType == JsonFieldType.VARIES
|
||||
|| descriptorFieldType == actualFieldType
|
||||
|| (fieldDescriptor.isOptional()
|
||||
|
||||
@@ -41,20 +41,25 @@ final class JsonFieldProcessor {
|
||||
|
||||
ExtractedField extract(String path, Object payload) {
|
||||
JsonFieldPath compiledPath = JsonFieldPath.compile(path);
|
||||
final List<Object> matches = new ArrayList<>();
|
||||
final List<Object> values = new ArrayList<>();
|
||||
traverse(new ProcessingContext(payload, compiledPath), new MatchCallback() {
|
||||
|
||||
@Override
|
||||
public void foundMatch(Match match) {
|
||||
matches.add(match.getValue());
|
||||
values.add(match.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void absent() {
|
||||
values.add(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
});
|
||||
if (matches.isEmpty()) {
|
||||
throw new FieldDoesNotExistException(path);
|
||||
if (values.isEmpty()) {
|
||||
values.add(ExtractedField.ABSENT);
|
||||
}
|
||||
return new ExtractedField(
|
||||
(compiledPath.getType() != PathType.SINGLE) ? matches : matches.get(0),
|
||||
(compiledPath.getType() != PathType.SINGLE) ? values : values.get(0),
|
||||
compiledPath.getType());
|
||||
}
|
||||
|
||||
@@ -427,6 +432,8 @@ final class JsonFieldProcessor {
|
||||
*/
|
||||
static class ExtractedField {
|
||||
|
||||
static final Object ABSENT = new Object();
|
||||
|
||||
private final Object value;
|
||||
|
||||
private final PathType type;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link JsonFieldType Types} for a field discovered in a JSON payload.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class JsonFieldTypes implements Iterable<JsonFieldType> {
|
||||
|
||||
private final Set<JsonFieldType> fieldTypes;
|
||||
|
||||
JsonFieldTypes(JsonFieldType fieldType) {
|
||||
this(Collections.singleton(fieldType));
|
||||
}
|
||||
|
||||
JsonFieldTypes(Set<JsonFieldType> fieldTypes) {
|
||||
this.fieldTypes = fieldTypes;
|
||||
}
|
||||
|
||||
JsonFieldType coalesce(boolean optional) {
|
||||
Set<JsonFieldType> types = new HashSet<>(this.fieldTypes);
|
||||
if (optional && types.size() > 1) {
|
||||
types.remove(JsonFieldType.NULL);
|
||||
}
|
||||
if (types.size() == 1) {
|
||||
return types.iterator().next();
|
||||
}
|
||||
return JsonFieldType.VARIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<JsonFieldType> iterator() {
|
||||
return this.fieldTypes.iterator();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -17,50 +17,45 @@
|
||||
package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.restdocs.payload.JsonFieldPath.PathType;
|
||||
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
|
||||
|
||||
/**
|
||||
* Resolves the type of a field in a JSON request or response payload.
|
||||
* Discovers the types of the fields found at a path in a JSON request or response
|
||||
* payload.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class JsonFieldTypeResolver {
|
||||
class JsonFieldTypesDiscoverer {
|
||||
|
||||
private final JsonFieldProcessor fieldProcessor = new JsonFieldProcessor();
|
||||
|
||||
JsonFieldType resolveFieldType(FieldDescriptor fieldDescriptor, Object payload) {
|
||||
ExtractedField extractedField = this.fieldProcessor
|
||||
.extract(fieldDescriptor.getPath(), payload);
|
||||
JsonFieldTypes discoverFieldTypes(String path, Object payload) {
|
||||
ExtractedField extractedField = this.fieldProcessor.extract(path, payload);
|
||||
Object value = extractedField.getValue();
|
||||
if (value instanceof Collection && extractedField.getType() == PathType.MULTI) {
|
||||
JsonFieldType commonType = null;
|
||||
for (Object item : (Collection<?>) value) {
|
||||
JsonFieldType fieldType = determineFieldType(item);
|
||||
if (commonType == null) {
|
||||
commonType = fieldType;
|
||||
}
|
||||
else if (fieldType != commonType) {
|
||||
if (!fieldDescriptor.isOptional()) {
|
||||
return JsonFieldType.VARIES;
|
||||
}
|
||||
if (commonType == JsonFieldType.NULL) {
|
||||
commonType = fieldType;
|
||||
}
|
||||
else if (fieldType != JsonFieldType.NULL) {
|
||||
return JsonFieldType.VARIES;
|
||||
}
|
||||
}
|
||||
Collection<?> values = (Collection<?>) value;
|
||||
if (allAbsent(values)) {
|
||||
throw new FieldDoesNotExistException(path);
|
||||
}
|
||||
return commonType;
|
||||
Set<JsonFieldType> fieldTypes = new HashSet<>();
|
||||
for (Object item : values) {
|
||||
fieldTypes.add(determineFieldType(item));
|
||||
}
|
||||
return new JsonFieldTypes(fieldTypes);
|
||||
}
|
||||
return determineFieldType(value);
|
||||
if (value == ExtractedField.ABSENT) {
|
||||
throw new FieldDoesNotExistException(path);
|
||||
}
|
||||
return new JsonFieldTypes(determineFieldType(value));
|
||||
}
|
||||
|
||||
private JsonFieldType determineFieldType(Object fieldValue) {
|
||||
if (fieldValue == null) {
|
||||
if (fieldValue == null || fieldValue == ExtractedField.ABSENT) {
|
||||
return JsonFieldType.NULL;
|
||||
}
|
||||
if (fieldValue instanceof String) {
|
||||
@@ -78,4 +73,13 @@ class JsonFieldTypeResolver {
|
||||
return JsonFieldType.NUMBER;
|
||||
}
|
||||
|
||||
private boolean allAbsent(Collection<?> values) {
|
||||
for (Object value : values) {
|
||||
if (value != ExtractedField.ABSENT) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -190,7 +190,7 @@ class XmlContentHandler implements ContentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object determineFieldType(FieldDescriptor fieldDescriptor) {
|
||||
public Object resolveFieldType(FieldDescriptor fieldDescriptor) {
|
||||
if (fieldDescriptor.getType() != null) {
|
||||
return fieldDescriptor.getType();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 org.springframework.restdocs.payload;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link FieldTypeResolver}.
|
||||
*
|
||||
* @author Mathias Düsterhöft
|
||||
*/
|
||||
public class FieldTypeResolverTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrownException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void returnJsonFieldTypeResolver() {
|
||||
assertThat(FieldTypeResolver.forContent("{\"field\": \"value\"}".getBytes(),
|
||||
MediaType.APPLICATION_JSON)).isInstanceOf(JsonContentHandler.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnXmlContentHandler() {
|
||||
assertThat(FieldTypeResolver.forContent("<a><b>5</b></a>".getBytes(),
|
||||
MediaType.APPLICATION_XML)).isInstanceOf(XmlContentHandler.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwOnInvalidContent() {
|
||||
this.thrownException.expect(PayloadHandlingException.class);
|
||||
FieldTypeResolver.forContent("some".getBytes(), MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* Tests for {@link JsonContentHandler}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Mathias Düsterhöft
|
||||
*/
|
||||
public class JsonContentHandlerTests {
|
||||
|
||||
@@ -39,14 +40,14 @@ public class JsonContentHandlerTests {
|
||||
public void typeForFieldWithNullValueMustMatch() {
|
||||
this.thrown.expect(FieldTypesDoNotMatchException.class);
|
||||
new JsonContentHandler("{\"a\": null}".getBytes())
|
||||
.determineFieldType(new FieldDescriptor("a").type(JsonFieldType.STRING));
|
||||
.resolveFieldType(new FieldDescriptor("a").type(JsonFieldType.STRING));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithNotNullAndThenNullValueMustMatch() {
|
||||
this.thrown.expect(FieldTypesDoNotMatchException.class);
|
||||
new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}".getBytes())
|
||||
.determineFieldType(
|
||||
.resolveFieldType(
|
||||
new FieldDescriptor("a[].id").type(JsonFieldType.STRING));
|
||||
}
|
||||
|
||||
@@ -54,7 +55,7 @@ public class JsonContentHandlerTests {
|
||||
public void typeForFieldWithNullAndThenNotNullValueMustMatch() {
|
||||
this.thrown.expect(FieldTypesDoNotMatchException.class);
|
||||
new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes())
|
||||
.determineFieldType(
|
||||
.resolveFieldType(
|
||||
new FieldDescriptor("a.[].id").type(JsonFieldType.STRING));
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ public class JsonContentHandlerTests {
|
||||
public void typeForOptionalFieldWithNumberAndThenNullValueIsNumber() {
|
||||
Object fieldType = new JsonContentHandler(
|
||||
"{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes())
|
||||
.determineFieldType(new FieldDescriptor("a[].id").optional());
|
||||
.resolveFieldType(new FieldDescriptor("a[].id").optional());
|
||||
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ public class JsonContentHandlerTests {
|
||||
public void typeForOptionalFieldWithNullAndThenNumberIsNumber() {
|
||||
Object fieldType = new JsonContentHandler(
|
||||
"{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes())
|
||||
.determineFieldType(new FieldDescriptor("a[].id").optional());
|
||||
.resolveFieldType(new FieldDescriptor("a[].id").optional());
|
||||
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@@ -78,7 +79,7 @@ public class JsonContentHandlerTests {
|
||||
public void typeForFieldWithNumberAndThenNullValueIsVaries() {
|
||||
Object fieldType = new JsonContentHandler(
|
||||
"{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes())
|
||||
.determineFieldType(new FieldDescriptor("a[].id"));
|
||||
.resolveFieldType(new FieldDescriptor("a[].id"));
|
||||
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@@ -86,14 +87,14 @@ public class JsonContentHandlerTests {
|
||||
public void typeForFieldWithNullAndThenNumberIsVaries() {
|
||||
Object fieldType = new JsonContentHandler(
|
||||
"{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes())
|
||||
.determineFieldType(new FieldDescriptor("a[].id"));
|
||||
.resolveFieldType(new FieldDescriptor("a[].id"));
|
||||
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForOptionalFieldWithNullValueCanBeProvidedExplicitly() {
|
||||
Object fieldType = new JsonContentHandler("{\"a\": null}".getBytes())
|
||||
.determineFieldType(
|
||||
.resolveFieldType(
|
||||
new FieldDescriptor("a").type(JsonFieldType.STRING).optional());
|
||||
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import java.util.Map;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
@@ -109,7 +111,7 @@ public class JsonFieldProcessorTests {
|
||||
new HashMap<String, Object>());
|
||||
payload.put("a", alpha);
|
||||
assertThat(this.fieldProcessor.extract("a[].b", payload).getValue())
|
||||
.isEqualTo(Arrays.asList("bravo"));
|
||||
.isEqualTo(Arrays.asList("bravo", ExtractedField.ABSENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,54 +167,61 @@ public class JsonFieldProcessorTests {
|
||||
Arrays.asList(4)));
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentTopLevelField() {
|
||||
this.fieldProcessor.extract("a", Collections.emptyMap());
|
||||
assertThat(this.fieldProcessor.extract("a", Collections.emptyMap()).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentNestedField() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", new HashMap<String, Object>());
|
||||
this.fieldProcessor.extract("a.b", payload);
|
||||
assertThat(this.fieldProcessor.extract("a.b", payload).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentNestedFieldWhenParentIsNotAMap() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", 5);
|
||||
this.fieldProcessor.extract("a.b", payload);
|
||||
assertThat(this.fieldProcessor.extract("a.b", payload).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentFieldWhenParentIsAnArray() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
HashMap<String, Object> alpha = new HashMap<>();
|
||||
alpha.put("b", Arrays.asList(new HashMap<String, Object>()));
|
||||
payload.put("a", alpha);
|
||||
this.fieldProcessor.extract("a.b.c", payload);
|
||||
assertThat(this.fieldProcessor.extract("a.b.c", payload).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentArrayField() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
this.fieldProcessor.extract("a[]", payload);
|
||||
assertThat(this.fieldProcessor.extract("a[]", payload).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentArrayFieldAsTypeDoesNotMatch() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", 5);
|
||||
this.fieldProcessor.extract("a[]", payload);
|
||||
assertThat(this.fieldProcessor.extract("a[]", payload).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test(expected = FieldDoesNotExistException.class)
|
||||
@Test
|
||||
public void nonExistentFieldBeneathAnArray() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
HashMap<String, Object> alpha = new HashMap<>();
|
||||
alpha.put("b", Arrays.asList(new HashMap<String, Object>()));
|
||||
payload.put("a", alpha);
|
||||
this.fieldProcessor.extract("a.b[].id", payload);
|
||||
assertThat(this.fieldProcessor.extract("a.b[].id", payload).getValue())
|
||||
.isEqualTo(Arrays.asList(ExtractedField.ABSENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* 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 org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonFieldTypeResolver}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldTypeResolverTests {
|
||||
|
||||
private final JsonFieldTypeResolver fieldTypeResolver = new JsonFieldTypeResolver();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrownException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void arrayField() throws IOException {
|
||||
assertFieldType(JsonFieldType.ARRAY, "[]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void topLevelArray() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("[]"),
|
||||
new ObjectMapper().readValue("[{\"a\":\"alpha\"}]", List.class)))
|
||||
.isEqualTo(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedArray() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[]"),
|
||||
createPayload("{\"a\": [{\"b\":\"bravo\"}]}")))
|
||||
.isEqualTo(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayNestedBeneathAnArray() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].b[]"),
|
||||
createPayload("{\"a\": [{\"b\": [ 1, 2 ]}]}")))
|
||||
.isEqualTo(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificFieldOfObjectInArrayNestedBeneathAnArray() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].b[].c"),
|
||||
createPayload("{\"a\": [{\"b\": [ {\"c\": 5}, {\"c\": 5}]}]}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void booleanField() throws IOException {
|
||||
assertFieldType(JsonFieldType.BOOLEAN, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectField() throws IOException {
|
||||
assertFieldType(JsonFieldType.OBJECT, "{}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullField() throws IOException {
|
||||
assertFieldType(JsonFieldType.NULL, "null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberField() throws IOException {
|
||||
assertFieldType(JsonFieldType.NUMBER, "1.2345");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringField() throws IOException {
|
||||
assertFieldType(JsonFieldType.STRING, "\"Foo\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedField() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a.b.c"),
|
||||
createPayload("{\"a\":{\"b\":{\"c\":{}}}}")))
|
||||
.isEqualTo(JsonFieldType.OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithSameType() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":2}]}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypes() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":true}]}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesAbsent() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":true}, { }]}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesAbsentWhenOptionalResolvesToVaries()
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(
|
||||
new FieldDescriptor("a[].id").optional(),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":true}, { }]}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesAbsent() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":1},{ }]}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesNull() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":true}, {\"id\":null}]}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenNotNullThenNullWhenRequiredHasVariesType()
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":null}]}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenNotNullThenNullWhenOptionalHasSpecificType()
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(
|
||||
new FieldDescriptor("a[].id").optional(),
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":null}]}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenNullThenNotNullWhenRequiredHasVariesType()
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":null},{\"id\":1}]}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenNullThenNotNullWhenOptionalHasSpecificType()
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(
|
||||
new FieldDescriptor("a[].id").optional(),
|
||||
createPayload("{\"a\":[{\"id\":null},{\"id\":1}]}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenEitherNullOrAbsent() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{},{\"id\":null}]}")))
|
||||
.isEqualTo(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsThatAreAllNull() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].id"),
|
||||
createPayload("{\"a\":[{\"id\":null},{\"id\":null}]}")))
|
||||
.isEqualTo(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentSingleFieldProducesFieldDoesNotExistException()
|
||||
throws IOException {
|
||||
this.thrownException.expect(FieldDoesNotExistException.class);
|
||||
this.thrownException.expectMessage(
|
||||
"The payload does not contain a field with the path 'a.b'");
|
||||
this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a.b"),
|
||||
createPayload("{\"a\":{}}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentMultipleFieldsProducesFieldDoesNotExistException()
|
||||
throws IOException {
|
||||
this.thrownException.expect(FieldDoesNotExistException.class);
|
||||
this.thrownException.expectMessage(
|
||||
"The payload does not contain a field with the path 'a[].b'");
|
||||
this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a[].b"),
|
||||
createPayload("{\"a\":[{\"c\":1},{\"c\":2}]}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leafWildcardWithCommonType() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a.*"),
|
||||
createPayload("{\"a\": {\"b\": 5, \"c\": 6}}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leafWildcardWithVaryingType() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a.*"),
|
||||
createPayload("{\"a\": {\"b\": 5, \"c\": \"six\"}}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intermediateWildcardWithCommonType() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a.*.d"),
|
||||
createPayload("{\"a\": {\"b\": {\"d\": 4}, \"c\": {\"d\": 5}}}}")))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intermediateWildcardWithVaryingType() throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("a.*.d"),
|
||||
createPayload("{\"a\": {\"b\": {\"d\": 4}, \"c\": {\"d\": \"four\"}}}}")))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
private void assertFieldType(JsonFieldType expectedType, String jsonValue)
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType(new FieldDescriptor("field"),
|
||||
createSimplePayload(jsonValue))).isEqualTo(expectedType);
|
||||
}
|
||||
|
||||
private Map<String, Object> createSimplePayload(String value) throws IOException {
|
||||
return createPayload("{\"field\":" + value + "}");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> createPayload(String json) throws IOException {
|
||||
return new ObjectMapper().readValue(json, Map.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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 org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonFieldTypesDiscoverer}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldTypesDiscovererTests {
|
||||
|
||||
private final JsonFieldTypesDiscoverer fieldTypeDiscoverer = new JsonFieldTypesDiscoverer();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrownException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void arrayField() throws IOException {
|
||||
assertThat(discoverFieldTypes("[]")).containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void topLevelArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("[]", "[{\"a\":\"alpha\"}]"))
|
||||
.containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[]", "{\"a\": [{\"b\":\"bravo\"}]}"))
|
||||
.containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayNestedBeneathAnArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].b[]", "{\"a\": [{\"b\": [ 1, 2 ]}]}"))
|
||||
.containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificFieldOfObjectInArrayNestedBeneathAnArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].b[].c",
|
||||
"{\"a\": [{\"b\": [ {\"c\": 5}, {\"c\": 5}]}]}"))
|
||||
.containsExactly(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void booleanField() throws IOException {
|
||||
assertThat(discoverFieldTypes("true")).containsExactly(JsonFieldType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectField() throws IOException {
|
||||
assertThat(discoverFieldTypes("{}")).containsExactly(JsonFieldType.OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullField() throws IOException {
|
||||
assertThat(discoverFieldTypes("null")).containsExactly(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberField() throws IOException {
|
||||
assertThat(discoverFieldTypes("1.2345")).containsExactly(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringField() throws IOException {
|
||||
assertThat(discoverFieldTypes("\"Foo\"")).containsExactly(JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedField() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.b.c", "{\"a\":{\"b\":{\"c\":{}}}}"))
|
||||
.containsExactly(JsonFieldType.OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithSameType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":2}]}"))
|
||||
.containsExactly(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypes() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":true}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesAbsent() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":true}, {}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.BOOLEAN,
|
||||
JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesAbsent() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":2}, {}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesNull() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id",
|
||||
"{\"a\":[{\"id\":1},{\"id\":2}, {\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER,
|
||||
JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesNull() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id",
|
||||
"{\"a\":[{\"id\":1},{\"id\":true}, {\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER,
|
||||
JsonFieldType.BOOLEAN, JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenEitherNullOrAbsent() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{},{\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsThatAreAllNull() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":null},{\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentSingleFieldProducesFieldDoesNotExistException()
|
||||
throws IOException {
|
||||
this.thrownException.expect(FieldDoesNotExistException.class);
|
||||
this.thrownException.expectMessage(
|
||||
"The payload does not contain a field with the path 'a.b'");
|
||||
discoverFieldTypes("a.b", "{\"a\":{}}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentMultipleFieldsProducesFieldDoesNotExistException()
|
||||
throws IOException {
|
||||
this.thrownException.expect(FieldDoesNotExistException.class);
|
||||
this.thrownException.expectMessage(
|
||||
"The payload does not contain a field with the path 'a[].b'");
|
||||
discoverFieldTypes("a[].b", "{\"a\":[{\"c\":1},{\"c\":2}]}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leafWildcardWithCommonType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*", "{\"a\": {\"b\": 5, \"c\": 6}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leafWildcardWithVaryingType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*", "{\"a\": {\"b\": 5, \"c\": \"six\"}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intermediateWildcardWithCommonType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*.d",
|
||||
"{\"a\": {\"b\": {\"d\": 4}, \"c\": {\"d\": 5}}}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intermediateWildcardWithVaryingType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*.d",
|
||||
"{\"a\": {\"b\": {\"d\": 4}, \"c\": {\"d\": \"four\"}}}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER,
|
||||
JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
private JsonFieldTypes discoverFieldTypes(String value) throws IOException {
|
||||
return discoverFieldTypes("field", "{\"field\":" + value + "}");
|
||||
}
|
||||
|
||||
private JsonFieldTypes discoverFieldTypes(String path, String json)
|
||||
throws IOException {
|
||||
return this.fieldTypeDiscoverer.discoverFieldTypes(path,
|
||||
new ObjectMapper().readValue(json, Object.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonFieldTypes}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldTypesTests {
|
||||
|
||||
@Test
|
||||
public void singleTypeCoalescesToThatType() {
|
||||
assertThat(new JsonFieldTypes(JsonFieldType.NUMBER).coalesce(false))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleTypeCoalescesToThatTypeWhenOptional() {
|
||||
assertThat(new JsonFieldTypes(JsonFieldType.NUMBER).coalesce(true))
|
||||
.isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleTypesCoalescesToVaries() {
|
||||
assertThat(
|
||||
new JsonFieldTypes(EnumSet.of(JsonFieldType.ARRAY, JsonFieldType.NUMBER))
|
||||
.coalesce(false)).isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAndNonNullTypesCoalescesToVaries() {
|
||||
assertThat(new JsonFieldTypes(EnumSet.of(JsonFieldType.ARRAY, JsonFieldType.NULL))
|
||||
.coalesce(false)).isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAndNonNullTypesCoalescesToNonNullTypeWhenOptional() {
|
||||
assertThat(new JsonFieldTypes(EnumSet.of(JsonFieldType.ARRAY, JsonFieldType.NULL))
|
||||
.coalesce(true)).isEqualTo(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user