5

I'm trying use JUnit / Hamcrest to assert that a collection contains at least one element that my custom logic asserts is true. I'm hoping there's some kind of Matcher like 'anyOf' that takes a lambda (or anonymous class definition) where I can define the custom logic. I've tried TypeSafeMatcher but can't figure out what to do with it.

I don't think that anyOf is what I'm looking for either as that seem to take a list of Matchers.

Alex Worden
  • 3,374
  • 6
  • 34
  • 34

2 Answers2

4

what are you testing? There's a good chance you could use a combination of matchers like hasItem, allOf and hasProperty, otherwise you could implement org.hamcrest.TypeSafeMatcher. I find looking at the source code of existing matchers helps. I've created a basic custom matcher below that matches on a property

public static class Foo {
    private int id;
    public Foo(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
}

@Test
public void customMatcher() {
    Collection<Foo> foos = Arrays.asList(new Foo[]{new Foo(1), new Foo(2)});
    assertThat(foos, hasItem(hasId(1)));
    assertThat(foos, hasItem(hasId(2)));
    assertThat(foos, not(hasItem(hasId(3))));
}

public static Matcher<Foo> hasId(final int expectedId) {
    return new TypeSafeMatcher<Foo>() {

        @Override
        protected void describeMismatchSafely(Foo foo, Description description) {
            description.appendText("was ").appendValue(foo.getId());
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("Foo with id ").appendValue(expectedId);
        }

        @Override
        protected boolean matchesSafely(Foo foo) {
            // Your custom matching logic goes here
            return foo.getId() == expectedId;
        }
    };
}
logee
  • 5,017
  • 1
  • 26
  • 34
0

Perhaps Matchers.hasItems() can help you?

List<String> strings = Arrays.asList("a", "bb", "ccc");

assertThat(strings, Matchers.hasItems("a"));
assertThat(strings, Matchers.hasItems("a", "bb"));

Matchers also have a method for providing other Matcher as arguments, i.e. hasItems(Matcher<? super >... itemMatchers).

Moreover, there are some methods working on arrays hasItemInArray(T element) and hasItemInArray(Matcher<? super > elementMatcher)

matsev
  • 32,104
  • 16
  • 121
  • 156