From 4627e2c39baa8cc50ebd0796171c9afe4fc88d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chmielarz?= Date: Wed, 20 Mar 2019 16:25:39 +0100 Subject: [PATCH] MapAssert.containsOnlyKeys (#63) * Adds more tests for MapAssert.containsOnly * Adds assertion for MapAssert.containsOnlyKeys --- .../assertj/vavr/api/AbstractMapAssert.java | 25 ++--- .../java/org/assertj/vavr/internal/Maps.java | 101 +++++++++++++---- .../api/MapAssert_containsOnlyKeys_Test.java | 106 ++++++++++++++++++ .../vavr/api/MapAssert_containsOnly_Test.java | 50 +++++++-- 4 files changed, 241 insertions(+), 41 deletions(-) create mode 100644 src/test/java/org/assertj/vavr/api/MapAssert_containsOnlyKeys_Test.java diff --git a/src/main/java/org/assertj/vavr/api/AbstractMapAssert.java b/src/main/java/org/assertj/vavr/api/AbstractMapAssert.java index 643cc9ac..3f269a05 100644 --- a/src/main/java/org/assertj/vavr/api/AbstractMapAssert.java +++ b/src/main/java/org/assertj/vavr/api/AbstractMapAssert.java @@ -15,12 +15,7 @@ import io.vavr.Tuple; import io.vavr.Tuple2; -import io.vavr.collection.Array; -import io.vavr.collection.HashMap; -import io.vavr.collection.List; import io.vavr.collection.Map; -import io.vavr.collection.Set; - import org.assertj.core.api.AbstractObjectAssert; import org.assertj.core.api.EnumerableAssert; import org.assertj.core.internal.ComparatorBasedComparisonStrategy; @@ -30,8 +25,6 @@ import java.util.Comparator; import java.util.function.BiConsumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; import java.util.stream.StreamSupport; import static org.assertj.core.error.ShouldBeEmpty.shouldBeEmpty; @@ -193,6 +186,18 @@ public SELF doesNotContainEntry(KEY key, VALUE value) { return myself; } + public SELF containsOnly(Iterable> entries) { + isNotNull(); + maps.assertContainsOnly(info, actual, entries); + return myself; + } + + public SELF containsOnlyKeys(KEY... keys) { + isNotNull(); + maps.assertContainsOnlyKeys(info, actual, keys); + return myself; + } + @Override public SELF hasSize(int expectedSize) { isNotNull(); @@ -230,10 +235,4 @@ public SELF usingDefaultElementComparator() { elementComparisonStrategy = StandardComparisonStrategy.instance(); return myself; } - - public SELF containsOnly(Iterable> entries) { - isNotNull(); - maps.assertContainsOnly(info, actual, entries); - return myself; - } } diff --git a/src/main/java/org/assertj/vavr/internal/Maps.java b/src/main/java/org/assertj/vavr/internal/Maps.java index 594b06eb..22f3898c 100644 --- a/src/main/java/org/assertj/vavr/internal/Maps.java +++ b/src/main/java/org/assertj/vavr/internal/Maps.java @@ -1,22 +1,18 @@ package org.assertj.vavr.internal; import io.vavr.Tuple2; -import io.vavr.collection.Array; -import io.vavr.collection.HashMap; -import io.vavr.collection.Map; -import io.vavr.collection.Set; +import io.vavr.collection.*; import org.assertj.core.api.AssertionInfo; import org.assertj.core.error.ShouldContainAnyOf; -import org.assertj.core.error.ShouldNotBeNull; -import org.assertj.core.error.ShouldNotContainNull; import org.assertj.core.internal.Failures; import org.assertj.core.internal.Objects; import java.util.function.Predicate; import static org.assertj.core.error.ShouldContain.shouldContain; -import static org.assertj.core.error.ShouldNotContain.shouldNotContain; import static org.assertj.core.error.ShouldContainOnly.shouldContainOnly; +import static org.assertj.core.error.ShouldContainOnlyKeys.shouldContainOnlyKeys; +import static org.assertj.core.error.ShouldNotContain.shouldNotContain; import static org.assertj.core.internal.CommonValidations.failIfEmptySinceActualIsNotEmpty; import static org.assertj.core.util.Objects.areEqual; import static org.assertj.core.util.Preconditions.checkArgument; @@ -99,6 +95,64 @@ public void assertDoesNotContain(AssertionInfo info, Map actual, } } + /** + * Asserts that the given {@code Map} contains the given entries only. + * + * @param key type + * @param value type + * @param info contains information about the assertion. + * @param actual the given {@code Map}. + * @param entries the entries that are expected to only be in the given {@code Map}. + * @throws AssertionError if the array of entries is {@code null}. + * @throws AssertionError if the array of entries is empty. + * @throws NullPointerException if any of the entries in the given array is {@code null}. + * @throws AssertionError if the given {@code Map} is {@code null}. + * @throws AssertionError if the given {@code Map} contains any of the given entries. + */ + public void assertContainsOnly(AssertionInfo info, Map actual, Iterable> entries) { + assertNotNull(info, actual); + failIfNull(entries); + if (actual.isEmpty() && !entries.iterator().hasNext()) { + return; + } + failIfEmpty(entries); + Map expected = HashMap.ofEntries(entries); + Map notExpected = actual.filter(notContainFrom(expected)); + if (!notExpected.isEmpty()) { + Map notFound = expected.filter(notContainFrom(actual)); + throw failures.failure(info, shouldContainOnly(actual, expected, notFound, notExpected)); + } + } + + /** + * Asserts that the given {@code Map} contains the given keys, in any order. + * + * @param key type + * @param value type + * @param info contains information about the assertion. + * @param actual the given {@code Map}. + * @param keys the keys that are expected to be in the given {@code Map}. + * @throws NullPointerException if the array of keys is {@code null}. + * @throws IllegalArgumentException if the array of keys is empty. + * @throws AssertionError if the given {@code Map} is {@code null}. + * @throws AssertionError if the given {@code Map} does not contain the given keys. + */ + public void assertContainsOnlyKeys(AssertionInfo info, Map actual, K[] keys) { + assertNotNull(info, actual); + failIfNull(keys); + if (actual.isEmpty() && keys.length == 0) { + return; + } + failIfEmpty(keys); + + Set expected = HashSet.of(keys); + Set notExpected = actual.keySet().filter(notContainFrom(expected)); + if (!notExpected.isEmpty()) { + Set notFound = expected.filter(notContainFrom(actual.keySet())); + throw failures.failure(info, shouldContainOnlyKeys(actual, expected, notFound, notExpected)); + } + } + private boolean containsEntry(Map actual, Tuple2 entry) { checkNotNull(entry, "Entries to look for should not be null"); return actual.containsKey(entry._1) && areEqual(actual.get(entry._1).get(), entry._2); @@ -108,6 +162,14 @@ private static void failIfEmpty(Tuple2[] entrie checkArgument(entries.length > 0, "The array of entries to look for should not be empty"); } + private static void failIfEmpty(Iterable> entries) { + checkArgument(entries.iterator().hasNext(), "The entries to look for should not be empty"); + } + + private static void failIfEmpty(K[] keys) { + checkArgument(keys.length > 0, "The array of keys to look for should not be empty"); + } + private static void failIfNullOrEmpty(Tuple2[] entries) { failIfNull(entries); failIfEmpty(entries); @@ -117,24 +179,23 @@ private static void failIfNull(Tuple2[] entries checkNotNull(entries, "The array of entries to look for should not be null"); } - private void assertNotNull(AssertionInfo info, Map actual) { - Objects.instance().assertNotNull(info, actual); + private static void failIfNull(Iterable> entries) { + checkNotNull(entries, "The entries to look for should not be null"); } - public void assertContainsOnly(AssertionInfo info, Map actual, Iterable> entries) { - if (entries == null) { - throw failures.failure("Expected entries should not be null"); - } else { - Map expected = HashMap.ofEntries(entries); - Map notExpected = actual.filter(notContainFrom(expected)); - if (!notExpected.isEmpty()) { - Map notFound = expected.filter(notContainFrom(actual)); - throw failures.failure(info, shouldContainOnly(actual, expected, notFound, notExpected)); - } - } + private static void failIfNull(K[] keys) { + checkNotNull(keys, "The array of keys to look for should not be null"); + } + + private void assertNotNull(AssertionInfo info, Map actual) { + Objects.instance().assertNotNull(info, actual); } private static Predicate> notContainFrom(Map map) { return tuple -> !map.contains(tuple); } + + private static Predicate notContainFrom(Set keys) { + return key -> !keys.contains(key); + } } diff --git a/src/test/java/org/assertj/vavr/api/MapAssert_containsOnlyKeys_Test.java b/src/test/java/org/assertj/vavr/api/MapAssert_containsOnlyKeys_Test.java new file mode 100644 index 00000000..cdf05181 --- /dev/null +++ b/src/test/java/org/assertj/vavr/api/MapAssert_containsOnlyKeys_Test.java @@ -0,0 +1,106 @@ +package org.assertj.vavr.api; + +/* + * 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. + *

+ * Copyright 2012-2019 the original author or authors. + */ + +import io.vavr.collection.HashMap; +import io.vavr.collection.Map; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull; +import static org.assertj.vavr.api.VavrAssertions.assertThat; + +class MapAssert_containsOnlyKeys_Test { + + @Test + void should_pass_if_Map_contains_only_given_keys() { + final Map actual = HashMap.of("key", "value"); + + assertThat(actual).containsOnlyKeys("key"); + } + + @Test + void should_fail_when_Map_is_null() { + assertThatThrownBy( + () -> assertThat((Map) null).containsOnlyKeys("key") + ) + .isInstanceOf(AssertionError.class) + .hasMessage(shouldNotBeNull().create()); + } + + @Test + void should_fail_if_keys_parameter_is_null() { + final Map actual = HashMap.of("key", "value"); + + assertThatThrownBy( + () -> assertThat(actual).containsOnlyKeys((String[]) null) + ) + .isInstanceOf(NullPointerException.class) + .hasMessage("The array of keys to look for should not be null"); + } + + @Test + void should_fail_if_keys_parameter_is_empty() { + final Map actual = HashMap.of("key", "value"); + final String[] keys = new String[0]; + + assertThatThrownBy( + () -> assertThat(actual).containsOnlyKeys(keys) + ) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("The array of keys to look for should not be empty"); + } + + @Test + void should_fail_if_Map_contains_more_than_given_keys() { + final Map actual = HashMap.of("key-1", "value-1", "key-2", "value-2"); + + assertThatThrownBy( + () -> assertThat(actual).containsOnlyKeys("key-1") + ) + .isInstanceOf(AssertionError.class) + .hasMessage( + "\n" + + "Expecting:\n" + + " \n" + + "to contain only following keys:\n" + + " \n" + + "keys not found:\n" + + " \n" + + "and keys not expected:\n" + + " \n" + ); + } + + @Test + void should_fail_if_Map_has_same_size_but_contains_different_keys() { + final Map actual = HashMap.of("key-1", "value-1", "key-2", "value-2"); + + assertThatThrownBy( + () -> assertThat(actual).containsOnlyKeys("key-1", "key-3") + ) + .isInstanceOf(AssertionError.class) + .hasMessage( + "\n" + + "Expecting:\n" + + " \n" + + "to contain only following keys:\n" + + " \n" + + "keys not found:\n" + + " \n" + + "and keys not expected:\n" + + " \n" + ); + } +} diff --git a/src/test/java/org/assertj/vavr/api/MapAssert_containsOnly_Test.java b/src/test/java/org/assertj/vavr/api/MapAssert_containsOnly_Test.java index b90ab0f9..050fda77 100644 --- a/src/test/java/org/assertj/vavr/api/MapAssert_containsOnly_Test.java +++ b/src/test/java/org/assertj/vavr/api/MapAssert_containsOnly_Test.java @@ -13,36 +13,70 @@ * Copyright 2012-2019 the original author or authors. */ -import org.junit.jupiter.api.Test; - +import io.vavr.Tuple2; import io.vavr.collection.HashMap; import io.vavr.collection.List; import io.vavr.collection.Map; +import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull; import static org.assertj.vavr.api.VavrAssertions.assertThat; class MapAssert_containsOnly_Test { + @Test - void should_pass_if_Map_contains_only_given_entry() { + void should_pass_if_Map_contains_only_given_entries() { final Map actual = HashMap.of("key", "value"); assertThat(actual).containsOnly(List.of(Map.entry("key", "value"))); } @Test - void should_shrug() { + void should_fail_when_Map_is_null() { + assertThatThrownBy( + () -> assertThat((Map) null).containsOnly(List.of(Map.entry("key", "value"))) + ) + .isInstanceOf(AssertionError.class) + .hasMessage(shouldNotBeNull().create()); + } + + @Test + void should_fail_if_entries_parameter_is_null() { final Map actual = HashMap.of("key", "value"); assertThatThrownBy( - () -> assertThat(actual).containsOnly(null) + () -> assertThat(actual).containsOnly(null) ) - .isInstanceOf(AssertionError.class) - .hasMessage("Expected entries should not be null"); + .isInstanceOf(NullPointerException.class) + .hasMessage("The entries to look for should not be null"); + } + + @Test + void should_fail_if_entries_parameter_is_empty_but_actual_Map_is_not() { + final Map actual = HashMap.of("key", "value"); + final Iterable> entries = List.empty(); + + assertThatThrownBy( + () -> assertThat(actual).containsOnly(entries) + ) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("The entries to look for should not be empty"); + } + + @Test + void should_fail_if_one_of_entries_is_null() { + final Map actual = HashMap.of("key", "value"); + final List> entries = List.empty(); + + assertThatThrownBy( + () -> assertThat(actual).containsOnly(entries.append(null)) + ) + .isInstanceOf(NullPointerException.class); } @Test - void should_fail_if_Map_contains_more_than_given_entry() { + void should_fail_if_Map_contains_more_than_given_entries() { final Map actual = HashMap.of("key-1", "value-1", "key-2", "value-2"); assertThatThrownBy(