2

The answer to this old question recommends Hamcrest for asserting on collections.

What happens if I want to assert a collection has multiple instances of an object?

list = newArrayList();
list.add(1);
list.add(1);
list.add(2);
assertThat(list, hasItems(1, 2, 2)); // This should fail
assertThat(list, hasItems(1, 2, 1)); // This should pass

The hamcrest code I tried does not care about multiplicity - both asserts above will pass.

Community
  • 1
  • 1
ripper234
  • 222,824
  • 274
  • 634
  • 905

6 Answers6

2

Guava's Multiset is intended to efficiently keep track of multiple occurrences of elements.

Multiset<E> multiset = HashMultiset.create(collection);

and then you have multiple occurrences of x if multiset.count(x) > 1.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1
assertEquals(2, Collections.frequency(list, 1));
assertEquals(1, Collections.frequency(list, 2));

Of course you could use Hamcrest notation on this if you want.

And the advantage is multi-fold over some other answers: you may not be the owner of the collection so you may not have control over what implementation to use. And furthermore, you are not restricted to the type of Collection (List, Set, etc.) that this technique can be used on.

Thanks for the question, I wouldn't have thought of this otherwise :-)

Kevin Welker
  • 7,719
  • 1
  • 40
  • 56
0

Write another assertion yourself. This assertion could use the following technique:

  • copy the collection to a new list
  • for each element that must be present, test if it is, and remove it from the list
  • if you want to check that there aren't more instances of an object, then for each element, test that it isn't in the list anymore.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

Maybe it is just me but seems like HashMap is your friend. Do I miss something?

aviad
  • 8,229
  • 9
  • 50
  • 98
  • 1
    Maybe. I am looking for a one-liner that lets me assert on collections, respecting multiplicity. Of course I could *build one using a hashmap*, but that's not a good answer ... it doesn't provide any new information. "Build it yourself" is the default answer, so it does't add much information. – ripper234 Feb 08 '12 at 08:28
  • I believe that my answer is constructive because if the collection population is under your control why not to choose an appropriate collection that fits the purpose? If this is not the situation (the collection is populated externally) I suggest you to rephrase your question in some way people could actually understand what you are looking for. – aviad Feb 08 '12 at 09:47
0

The easiest technique I can think of is sorting the list first and then using equality comparison:

Collections.sort(list);

And then:

assertEquals(Arrays.asList(1, 1, 2), list);
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
0

You can use Guava's Multimap, which is basically a map of keys -> list of values. In this case, you don't care so much about the list of values but its size. You would create the following multimap from your list:

1 -> [1, 1]
2 -> [2]

Then you can

Assert.assertEquals(2, map.get(1).size());

which makes sure that there are exactly two "1"'s in your original list.

If you don't want to depend on Guava, simply create a Map of each number to its count, which requires a bit more bookkeeping, but still pretty simple overall.

Cedric Beust
  • 15,480
  • 2
  • 55
  • 55