How would you succinctly assert the equality of Collection elements, specifically a Set in JUnit 4?
If you want to check whether a List or Set contains a set of specific values (instead of comparing it with an already existing collection), often the toString method of collections is handy:
String[] actualResult = calltestedmethod();
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());
List otherResult = callothertestedmethod();
assertEquals("[42, mice]", otherResult.toString());
This is a bit shorter than first constructing the expected collection and comparing it with the actual collection, and easier to write and correct.
(Admittedly, this is not a particularily clean method, and can't distinguish an element "foo, bar" from two elements "foo" and "bar". But in practice I think it's most important that it's easy and fast to write tests, otherwise many developers just won't without being pressed.)
You can assert that the two Sets are equal to one another, which invokes the Set equals() method.
public class SimpleTest {
private Set<String> setA;
private Set<String> setB;
@Before
public void setUp() {
setA = new HashSet<String>();
setA.add("Testing...");
setB = new HashSet<String>();
setB.add("Testing...");
}
@Test
public void testEqualSets() {
assertEquals( setA, setB );
}
}
This @Test will pass if the two Sets are the same size and contain the same elements.
Using Hamcrest:
assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));
This works also when the sets have different datatypes, and reports on the difference instead of just failing.
Apache commons to the rescue again.
assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));
Works like a charm. I don't know why but I found that with collections the following assertEquals(coll1, coll2) doesn't always work. In the case where it failed for me I had two collections backed by Sets. Neither hamcrest nor junit would say the collections were equal even though I knew for sure that they were. Using CollectionUtils it works perfectly.
A particularly interesting case is when you compare
java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]>
and
java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>
So far, the only solution I see is to change both of them into sets
assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));
Or I could compare them element by element.
I like the solution of Hans-Peter Störr... But I think it is not quite correct. Sadly containsInAnyOrder does not accept a Collection of objetcs to compare to. So it has to be a Collection of Matchers:
assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))
The import are:
import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;