Troy Daniels
Troy Daniels

Reputation: 3598

Use Hamcrest to check if some elements are in a Collection

I am trying to test code where I expect a collection to have 2 of three specific values. Is there a concise way to test that with Hamcrest 1.3?

I want something like this:

Collection<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");
// Remove an indeterminate element
set.iterator().next().remove();

// What the matcher actually is is the question
assertThat(set, hasSomeOf("A", "B", "C")); 
assertThat(set, hasSize(2));

So long as set contains two of the three values, the code is working correctly, and which one is missing will actually depend on String hash codes in the real example.

I think this might be the best way to handle it:

Collection<String> expected = Arrays.asList("A", "B", "C");
for (String value: set) {
  assertThat(value, isIn(expected));
  expected.remove(value);
}

That also has the drawback that I cannot use additional matchers, which I would like in my real case. (To reuse my fictitious matcher, I would like do to something like hasSome(startsWith("A"), startsWith("B"), startsWith("C"))

Clarification

If set contains something not in the arguments to hasSomeOf, then the matcher fails.

Upvotes: 2

Views: 1452

Answers (1)

Jaims
Jaims

Reputation: 1575

I believe the matcher you're looking for is everyItem() in combination with oneOf() or anyOf(). The scenario ["C", "H"] should fail for hasSome("A", "B", "C"), could be written as follows:

assertThat(set, everyItem(is(oneOf("A", "B", "C"))));

And would result in the following failure when the item H were added:

Expected: every item is is one of {"A", "B", "C"}
     but: an item was "H"

For your other scenario in which you'd like to include multiple matchers, you can simply replace the expectation.

assertThat(set, everyItem(is(anyOf(startsWith("A"), startsWith("B"), startsWith("C")))));

This would then result into:

Expected: every item is is (a string starting with "A" or a string starting with "B" or a string starting with "C")
     but: an item was "H"

Upvotes: 2

Related Questions