How would you succinctly assert the equality of Collection
elements, specifically a Set
in JUnit 4?
-
2check this SO post http://stackoverflow.com/questions/1086691/collectionassert-in-junit – Teja Kantamneni Feb 22 '10 at 18:46
-
Are you trying to assert that two Sets are equal to each other (contain the same elements), or that two elements of the same Set are equal? – Bill the Lizard Feb 22 '10 at 18:55
-
I need to see that the elements of two Sets are equal – Eqbal Feb 22 '10 at 18:58
11 Answers
You can assert that the two Set
s 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 Set
s are the same size and contain the same elements.

- 5,141
- 5
- 38
- 59

- 398,270
- 210
- 566
- 880
-
8This does not display very good results in the report. If your toStrings are clearly defined it is better, but still not good (A small difference can end up with a page of text) – Bill K Sep 17 '12 at 18:13
-
Uhm, how come I get: java.lang.AssertionError: expected: java.util.Hashtable<{CompanyName=8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric=sZwmXAdYKv, Category=AvrIfd, QuoteId=4342740204922826921}> but was: java.util.Hashtable<{CompanyName=8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric=sZwmXAdYKv, Category=AvrIfd, QuoteId=4342740204922826921}> – Giovanni Botta Mar 28 '13 at 15:27
-
4@Giodude Do you have `equals` and `hashCode` implemented in the class that you're storing in your Hashtable? – Bill the Lizard Mar 28 '13 at 15:40
-
As you can see those are just strings and a long... I'm testing Avro to serialize and de-serialize a map and that's the result. I think there's gotta be something fishy going on with the way the strings are serialized and de-serialized that makes the test fail but I can't seem to find the problem. – Giovanni Botta Mar 28 '13 at 17:35
-
Didn't work for me even though I am comparing two HashSet
. @MattFriedman answer actually works for my use case. – bluecollarcoder Nov 06 '14 at 00:28 -
I've found that if assertEquals is failing for two map comparisons with complex nesting and custom types, but you're sure that they're equal, then you should double check that all your custom types are implementing equals. If you've forgotten even one, then you'll just get the unhelpful message that you're map references are different. – RTF Jan 14 '15 at 11:41
-
I'm afraid that the tests will fail for those cases that has a HashSet from one side and a decorated hash set from the other side (for example, an immutable hash set). I would recommend to use comparison using twice the containsAll method. A = B if A contains B and B contains A. – Victor Sep 18 '15 at 18:45
-
I came upon this question because I think assuming `HashSet
` is an unreasonable assumption. If the publicly stated return type is `Set – Alonso del Arte Jul 03 '23 at 20:44`, then the class under test should have the freedom to use any implementation of `Set `.
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.

- 35,458
- 16
- 93
- 163

- 1,535
- 1
- 17
- 24
-
21This is actually trivial, the tricky part is to clearly indicate the difference to the caller – Bill K Sep 17 '12 at 18:15
-
2The accepted answer is a good answer for the original question (unit test specifically for two Sets) but this answer with CollectionUtils is I think a better answer for the most general case. I wasn't able to compare a Collection and a Set unless using CollectionUtils. – Jason Mar 15 '17 at 09:46
with hamcrest:
assertThat(s1, is(s2));
with plain assert:
assertEquals(s1, s2);
NB:t the equals() method of the concrete set class is used

- 114,442
- 31
- 189
- 228
-
1I prefer this method since Hamcrest comes with JUnit 4 so it is all there no need for other libraries. – JRSofty Jan 25 '16 at 13:19
-
2
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.
-
Actually, there are several solutions for that presented in the other answers. Sets are a bit unfortunate for this, anyway, since they ignore the order. Perhaps ArrayList? – Dr. Hans-Peter Störr May 24 '17 at 15:46
As an additional method that is array based ... you can consider using unordered array assertions in junitx . Although the Apache CollectionUtils example will work, there is a pacakge of solid assertion extensions there as well :
I think that the
ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});
approach will be much more readable and debuggable for you (all Collections support toArray(), so it should be easy enough to use the ArrayAssert methods.
Of course the downside here is that, junitx is an additional jar file or maven entry...
<dependency org="junit-addons" name="junit-addons" rev="1.4"/>

- 17,388
- 22
- 92
- 167
Check this article. One example from there:
@Test
public void listEquality() {
List<Integer> expected = new ArrayList<Integer>();
expected.add(5);
List<Integer> actual = new ArrayList<Integer>();
actual.add(5);
assertEquals(expected, actual);
}

- 5,031
- 17
- 33
- 41

- 64,384
- 92
- 238
- 332
-
short but great Link, explains really fast what you can do with Junit4- – Johannes Jan 28 '13 at 10:38
-
1The link is broken. Any chance you can find an archived version online or summarize its contents? – pzp Nov 20 '17 at 18:08
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.

- 25,298
- 30
- 102
- 139
-
2What is the import for isIn? IntelliJ can't resolve the import with any hamcret package. – fabien Dec 10 '17 at 18:09
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 Matcher
s:
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;

- 733
- 6
- 16
You can do it like that ->
assertThat(actualSet).containsExactlyInAnyOrder(expectedSet);

- 91
- 1
- 6
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.)

- 25,298
- 30
- 102
- 139
-
This makes the result of your unit test depend on the implementation of toString from list. If they decide to change the formatting the unit test wont work anymore. I would not consider this safe. – Laurens Op 't Zandt Mar 24 '17 at 11:36
-
@LaurensOp'tZandt You mean Oracle changing the format of Collection.toList()? That's certainly not going to happen. You are, however, right that's not particularily clean. But in practice, my impression that it's most important that it is very easy to write tests. – Dr. Hans-Peter Störr Mar 25 '17 at 19:13
-
I agree, I think the toString method won't likely chance. So probably it will keep working. I just wanted to point out that its not a very clean way. But indeed it is very easy. One problem that arises is when comparing sets. Since their order is not guaranteed. – Laurens Op 't Zandt Mar 26 '17 at 19:57
containsInAnyOrder() - help me.
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 11 '23 at 17:40
-
This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34667877) – Bö macht Blau Jul 12 '23 at 19:04