I am trying to check if two collections are the same using Assertions. They are supposed to be the same, even if their elements are in different order.
Here is my method for checking equality:
public static <T> void assertCollectionsAreEquals (Collection<T> expected, Collection<T> actual, String message) {
Assertions.assertEquals(expected, actual, message);
}
Example collections:
Collection <Integer> one = new ArrayList<Integer>();
Collection <Integer> two = new ArrayList<Integer>();
Collection <Integer> three = new ArrayList<Integer>();
one.add(1);
one.add(2);
two.add(1);
two.add(2);
three.add(2);
three.add(1);
So my collections look like this:
One:[1, 2]
Two:[1, 2]
Three:[2, 1]
Test:
assertCollectionsAreEquals(one, two, "Not Equals");
assertCollectionsAreEquals(one, three, "Not Equals");
Output:
Exception in thread "main" org.opentest4j.AssertionFailedError: Not Equals ==> expected: <[1, 2]> but was: <[2, 1]>
How do I make my tests succeed for all of my test collections?
To check equality of two collections, the size of the two collections should be compared, next a difference may be calculated by removing elements in collection c2
from the copy of collection c1
and if it's empty the collections are equal:
public static <T> boolean areCollectionsEqual(Collection<T> c1, Collection<T> c2) {
if (c1 == c2) return true;
if (c1 == null || c2 == null || c1.size() != c2.size()) {
return false;
}
Collection<T> tmp = new ArrayList<>(c1);
for (T item : c2) {
if (!tmp.remove(item)) {
return false;
}
}
return tmp.isEmpty();
}
Such method allows to compare different types of collections (e.g. List
to Set
)
Then common assertTrue
/ assertFalse
may be used in tests:
public static <T> void assertCollectionsAreEqual(Collection<T> expected, Collection<T> actual, String message) {
Assertions.assertTrue(areCollectionsEqual(expected, actual), message);
}
public static <T> void assertCollectionsAreNotEqual(Collection<T> expected, Collection<T> actual, String message) {
Assertions.assertFalse(areCollectionsEqual(expected, actual), message);
}
Update Collection::removeAll
may produce incorrect result in the case when the collections contain the same elements with different frequencies. e.g. List.of (1, 2, 2, 2)
and List.of (1, 2, 1, 2)
, so it was replaced with iterative remove
.