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 008f6366..0f2932f8 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 @@ -75,7 +75,7 @@ private boolean isNestedBeneathMissingOptionalField(FieldDescriptor descriptor, List candidates = new ArrayList<>(this.fieldDescriptors); candidates.remove(descriptor); for (FieldDescriptor candidate : candidates) { - if (candidate.isOptional() && descriptor.getPath().startsWith(candidate.getPath()) + if (candidate.isOptional() && isNestedBeneath(candidate.getPath(), descriptor.getPath()) && isMissing(candidate, payload)) { return true; } @@ -83,6 +83,10 @@ && isMissing(candidate, payload)) { return false; } + private boolean isNestedBeneath(String ancestorPath, String path) { + return path.equals(ancestorPath) || path.startsWith(ancestorPath + ".") || path.startsWith(ancestorPath + "["); + } + private boolean isMissing(FieldDescriptor candidate, Object payload) { if (!this.fieldProcessor.hasField(candidate.getPath(), payload)) { return true; 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 de61f3be..e421ab31 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 @@ -158,6 +158,26 @@ void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsNotPresentIsN assertThat(missingFields.size()).isEqualTo(0); } + @Test + void describedFieldThatIsNotPresentWithPathPrefixedByPathOfMissingOptionalFieldIsConsideredMissing() { + List descriptors = Arrays.asList(new FieldDescriptor("a").optional(), + new FieldDescriptor("ab")); + List missingFields = new JsonContentHandler("{\"c\":\"charlie\"}".getBytes(), descriptors) + .findMissingFields(); + assertThat(missingFields.size()).isEqualTo(1); + assertThat(missingFields.get(0).getPath()).isEqualTo("ab"); + } + + @Test + void describedNestedFieldThatIsNotPresentWithPathPrefixedByPathOfMissingOptionalFieldIsConsideredMissing() { + List descriptors = Arrays.asList(new FieldDescriptor("a.b").optional(), + new FieldDescriptor("a.bc")); + List missingFields = new JsonContentHandler("{\"a\":{}}".getBytes(), descriptors) + .findMissingFields(); + assertThat(missingFields.size()).isEqualTo(1); + assertThat(missingFields.get(0).getPath()).isEqualTo("a.bc"); + } + @Test void describedFieldThatIsNotPresentNestedBeneathOptionalArrayThatIsEmptyIsNotConsideredMissing() { List descriptors = Arrays.asList(new FieldDescriptor("outer"),