Reputation: 3598
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
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