Standard Hamcrest matcher to check if collection is empty or null?
Asked Answered
O

4

9

Is there a shorter version of the following assert statement using standard Hamcrest matchers?

Collection<Element> collection = ...

assertThat(collection, is(anyOf(nullValue(Collection.class), 
     emptyCollectionOf(Element.class))));

I realize there is a way to create a custom matcher, was hoping that maybe there is already something in place that addresses this without any additional code change.

Odle answered 21/2, 2018 at 14:55 Comment(1)
There is a shorter version, if your code is changed to never return null in place of an empty collection.Defamatory
D
13

There is no out-of-the-box solution, and worse, either() can't be used due to this bug. So the shortest way is this:

assertThat(collection, anyOf(nullValue(), empty()));
Dessert answered 22/2, 2018 at 21:28 Comment(0)
C
2

One way to achieve this would be to create a custom Hamcrest matcher, which combines already available matches (like IsNull.nullValue() and IsEmptyCollection.empty()).

But generally speaking an assert should assert for one thing only. My opinion is that it's not a huge pain to have two matchers in succession and it's more readable later.

Also there's another preferred pattern - when returning a collection, prefer returning empty collection instead of null. The idea is to avoid unnecessary null checks.

Cabstand answered 21/2, 2018 at 14:58 Comment(2)
I agree in principle with your second statement. In practice though this combined situation comes up fairly often, so would be nice to have something like emptyOrNull()Odle
well different approaches are possible - you can always create a custom matcher (as suggested in other answers as well), or just wrap the two assertions in a utility method "nullOrEmpty(testTarget)" and call that in all places needed. In the end of the day - it's just test cases - if it tests the intended functionality - it's good to go. I really don't see a lot of benefit of squashing these two lines in a single assertion.Cabstand
R
1

The only way I can think of is to write your own Matcher

class EmptyOrNull extends BaseMatcher<Collection> {
    public boolean matches(Object o) {
        boolean result = o == null;
        if (o instanceof Collection) {
            result = ((Collection) o).isEmpty();
        }
        return result;
    }
    public String describeMismatch(Object item, Description description) {
        return "not null or empty!";
    }
    public static Matcher<Collection> emptyOrNull() { return new EmptyOrNull(); }
}

and then you can use the shorter version.

assertThat(collection, emptyOrNull());
Roomer answered 21/2, 2018 at 15:7 Comment(0)
C
0

Consider a simple imperative solution using Assert.fail.

if (collection != null && !collection.isEmpty()) {
    fail(collection.toString());
}
Cacodemon answered 21/2, 2018 at 15:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.