From b3bbe7c2cdffdc528e670abc5582f5dc6d80be94 Mon Sep 17 00:00:00 2001 From: Lukas Krecan Date: Wed, 19 May 2021 20:00:36 +0200 Subject: [PATCH] Fix containsEntry --- .../jsonunit/assertj/JsonMapAssert.java | 51 ++++++++++++++----- .../test/base/AbstractAssertJTest.java | 26 ++++++++++ 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/json-unit-assertj/src/main/java/net/javacrumbs/jsonunit/assertj/JsonMapAssert.java b/json-unit-assertj/src/main/java/net/javacrumbs/jsonunit/assertj/JsonMapAssert.java index 2430ce392..24701cbb6 100644 --- a/json-unit-assertj/src/main/java/net/javacrumbs/jsonunit/assertj/JsonMapAssert.java +++ b/json-unit-assertj/src/main/java/net/javacrumbs/jsonunit/assertj/JsonMapAssert.java @@ -23,10 +23,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import static java.util.Arrays.stream; +import static java.util.Objects.deepEquals; +import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.entry; +import static org.assertj.core.error.ShouldContain.shouldContain; import static org.assertj.core.error.ShouldContainValue.shouldContainValue; import static org.assertj.core.error.ShouldNotContainValue.shouldNotContainValue; import static org.assertj.core.util.Arrays.array; @@ -116,7 +121,7 @@ public JsonMapAssert containsEntry(String key, Object value) { @SafeVarargs @Override - public final JsonMapAssert containsAnyOf(Map.Entry... entries) { + public final JsonMapAssert containsAnyOf(Entry... entries) { return super.containsAnyOf(wrap(entries)); } @@ -127,20 +132,38 @@ public JsonMapAssert containsAllEntriesOf(Map other) { @SafeVarargs @Override - public final JsonMapAssert containsExactly(Map.Entry... entries) { + public final JsonMapAssert containsExactly(Entry... entries) { return super.containsExactly(wrap(entries)); } @SafeVarargs @Override - public final JsonMapAssert containsOnly(Map.Entry... entries) { + public final JsonMapAssert containsOnly(Entry... entries) { return super.containsOnly(wrap(entries)); } @Override @SafeVarargs - public final JsonMapAssert contains(Map.Entry... entries) { - return super.contains(wrap(entries)); + public final JsonMapAssert contains(Entry... expected) { + List> notFound = stream(expected).filter(entry -> !doesContainEntry(entry)).collect(toList()); + if (!notFound.isEmpty()) { + throwAssertionError(shouldContain(actual, expected, notFound)); + } + return this; + } + + private boolean doesContainEntry(Entry entry) { + String key = entry.getKey(); + if (!actual.containsKey(key)) { + return false; + } + Object actualValue = actual.get(key); + if (entry.getValue() instanceof Node) { + Node value = (Node) entry.getValue(); + return isSimilar(actualValue, value); + } else { + return deepEquals(actualValue, entry.getValue()); + } } @Override @@ -151,17 +174,17 @@ public JsonMapAssert containsValues(Object... values) { @NotNull @SuppressWarnings("unchecked") - private Map.Entry[] wrap(Map.Entry[] entries) { - return stream(entries).map(this::wrapEntry).toArray(Map.Entry[]::new); + private Entry[] wrap(Entry[] entries) { + return stream(entries).map(this::wrapEntry).toArray(Entry[]::new); } @SuppressWarnings("unchecked") - private Map.Entry[] toEntries(Map map) { - return map.entrySet().toArray(new Map.Entry[0]); + private Entry[] toEntries(Map map) { + return map.entrySet().toArray(new Entry[0]); } - private Map.Entry wrapEntry(Map.Entry entry) { + private Entry wrapEntry(Entry entry) { if (entry.getValue() instanceof Node) { return entry(entry.getKey(), ((Node) entry.getValue()).getValue()); } else { @@ -181,7 +204,7 @@ public JsonMapAssert hasFieldOrProperty(String name) { } /** - * Does not work. Use {@link #contains(Map.Entry[])} instead. + * Does not work. Use {@link #contains(Entry[])} instead. * https://github.com/lukas-krecan/JsonUnit/issues/324 */ @Override @@ -240,6 +263,10 @@ private JsonMapAssert compare(@Nullable Object other, @NotNull Configuration con } private boolean contains(Object expected) { - return actual.entrySet().stream().anyMatch(kv -> Diff.create(expected, kv.getValue(), "fullJson", path.asPrefix(), configuration).similar()); + return actual.entrySet().stream().anyMatch(entry -> isSimilar(entry.getValue(), expected)); + } + + private boolean isSimilar(Object actual, Object expected) { + return Diff.create(expected, actual, "fullJson", path.asPrefix(), configuration).similar(); } } diff --git a/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractAssertJTest.java b/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractAssertJTest.java index 6238e85d1..2e061bd40 100644 --- a/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractAssertJTest.java +++ b/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractAssertJTest.java @@ -138,6 +138,32 @@ void containsEntryShouldWork() { ); } + @Test + void containsEntryShouldWorkWithMatcher() { + String json = "{\"a\": 1, \"b\": 2}"; + assertThatJson(json).isObject().containsEntry("a", json("\"${json-unit.any-number}\"")); + assertThatJson(json).isObject().contains(entry("a", json("\"${json-unit.any-number}\""))); + } + + @Test + void containsEntryShouldFailWithMatcher() { + String json = "{\"a\": 1, \"b\": 2}"; + + assertThatThrownBy(() -> + assertThatJson(json).isObject().contains( + entry("a", json("\"${json-unit.any-string}\"")), + entry("b", json("\"${json-unit.any-number}\"")) + ) + ).hasMessage("[Different value found in node \"\"] \n" + + "Expecting map:\n" + + " {\"a\":1,\"b\":2}\n" + + "to contain:\n" + + " [MapEntry[key=\"a\", value=\"${json-unit.any-string}\"],\n" + + " MapEntry[key=\"b\", value=\"${json-unit.any-number}\"]]\n" + + "but could not find the following map entries:\n" + + " [MapEntry[key=\"a\", value=\"${json-unit.any-string}\"]]\n"); + } + @Test void containsValuesShouldPass() { String json = "{\"a\": 1, \"b\": 2}";