Skip to content

Commit 2b5eab3

Browse files
committed
Improve error message when extracting a sometimes absent sub-section
Fixes gh-715
1 parent c3cb7af commit 2b5eab3

File tree

4 files changed

+45
-6
lines changed

4 files changed

+45
-6
lines changed

spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractor.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 the original author or authors.
2+
* Copyright 2014-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Set;
24+
import java.util.TreeSet;
2425
import java.util.stream.Collectors;
2526

2627
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -93,7 +94,9 @@ public byte[] extractSubsection(byte[] payload, MediaType contentType, List<Fiel
9394
List<?> extractedList = (List<?>) value;
9495
JsonContentHandler contentHandler = new JsonContentHandler(payload, descriptorsByPath.values());
9596
Set<JsonFieldPath> uncommonPaths = JsonFieldPaths.from(extractedList).getUncommon().stream()
96-
.map((path) -> JsonFieldPath.compile(this.fieldPath + "." + path)).filter((path) -> {
97+
.map((path) -> JsonFieldPath
98+
.compile((path.equals("")) ? this.fieldPath : this.fieldPath + "." + path))
99+
.filter((path) -> {
97100
FieldDescriptor descriptorForPath = descriptorsByPath.getOrDefault(path,
98101
new FieldDescriptor(path.toString()));
99102
return contentHandler.isMissing(descriptorForPath);
@@ -105,7 +108,8 @@ public byte[] extractSubsection(byte[] payload, MediaType contentType, List<Fiel
105108
String message = this.fieldPath + " identifies multiple sections of "
106109
+ "the payload and they do not have a common structure. The "
107110
+ "following non-optional uncommon paths were found: ";
108-
message += uncommonPaths;
111+
message += uncommonPaths.stream().map(JsonFieldPath::toString)
112+
.collect(Collectors.toCollection(TreeSet::new));
109113
throw new PayloadHandlingException(message);
110114
}
111115
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonFieldPaths.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2018 the original author or authors.
2+
* Copyright 2014-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@
2424
import java.util.Map.Entry;
2525
import java.util.Set;
2626

27+
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
28+
2729
/**
2830
* {@code JsonFieldPaths} provides support for extracting fields paths from JSON
2931
* structures and identifying uncommon paths.
@@ -69,6 +71,9 @@ private static void from(Set<String> paths, String parent, Object object) {
6971
else if (object instanceof Map) {
7072
from(paths, parent, (Map<?, ?>) object);
7173
}
74+
else if (object.equals(ExtractedField.ABSENT)) {
75+
paths.add(parent);
76+
}
7277
}
7378

7479
private static void from(Set<String> paths, String parent, List<?> items) {

spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractorTests.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 the original author or authors.
2+
* Copyright 2014-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -107,6 +107,25 @@ public void extractMapSubsectionWithVaryingStructureFromMultiElementArrayInAJson
107107
"{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6, \"d\": 7}}]}".getBytes(), MediaType.APPLICATION_JSON);
108108
}
109109

110+
@Test
111+
public void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMap()
112+
throws JsonParseException, JsonMappingException, IOException {
113+
this.thrown.expect(PayloadHandlingException.class);
114+
this.thrown.expectMessage("The following non-optional uncommon paths were found: [*.d, *.d.e, *.d.f]");
115+
new FieldPathPayloadSubsectionExtractor("*.d").extractSubsection(
116+
"{\"a\":{\"b\":1},\"c\":{\"d\":{\"e\":1,\"f\":2}}}".getBytes(), MediaType.APPLICATION_JSON);
117+
}
118+
119+
@Test
120+
public void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMapWhereAllSubsectionFieldsAreOptional()
121+
throws IOException {
122+
this.thrown.expect(PayloadHandlingException.class);
123+
this.thrown.expectMessage("The following non-optional uncommon paths were found: [*.d]");
124+
new FieldPathPayloadSubsectionExtractor("*.d").extractSubsection(
125+
"{\"a\":{\"b\":1},\"c\":{\"d\":{\"e\":1,\"f\":2}}}".getBytes(), MediaType.APPLICATION_JSON,
126+
Arrays.asList(new FieldDescriptor("e").optional(), new FieldDescriptor("f").optional()));
127+
}
128+
110129
@Test
111130
@SuppressWarnings("unchecked")
112131
public void extractMapSubsectionWithVaryingStructureDueToOptionalFieldsFromMultiElementArrayInAJsonMap()

spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonFieldPathsTests.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 the original author or authors.
2+
* Copyright 2014-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
2222
import com.fasterxml.jackson.databind.ObjectMapper;
2323
import org.junit.Test;
2424

25+
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
26+
2527
import static org.assertj.core.api.Assertions.assertThat;
2628

2729
/**
@@ -74,6 +76,15 @@ public void missingEntriesInNestedMapAreIdentifiedAsUncommon() {
7476
.getUncommon()).containsExactly("b.c", "b.d");
7577
}
7678

79+
@Test
80+
public void absentItemFromFieldExtractionCausesAllPresentFieldsToBeIdentifiedAsUncommon() {
81+
assertThat(
82+
JsonFieldPaths
83+
.from(Arrays.asList(ExtractedField.ABSENT, ("{\"a\": 1, \"b\": {\"c\": 1}}"),
84+
json("{\"a\": 1, \"b\": {\"c\": 1}}"), json("{\"a\": 1, \"b\": {\"d\": 2}}")))
85+
.getUncommon()).containsExactly("", "a", "b", "b.c", "b.d");
86+
}
87+
7788
@Test
7889
public void missingEntryBeneathArrayIsIdentifiedAsUncommon() {
7990
assertThat(JsonFieldPaths

0 commit comments

Comments
 (0)