164

I was wondering if anyone knew of a way to check if a List is empty using assertThat() and Matchers?

Best way I could see just use JUnit:

assertFalse(list.isEmpty());

But I was hoping that there was some way to do this in Hamcrest.

palacsint
  • 28,416
  • 10
  • 82
  • 109
Ian Dallas
  • 12,451
  • 19
  • 58
  • 82
  • 2
    For a better solution, vote for: http://code.google.com/p/hamcrest/issues/detail?id=97 – Fabricio Lemos Oct 02 '10 at 15:40
  • 2
    @FabricioLemos issue#97 seems to be resolved and merget to master git branch. Lets hope it will be soon in next hamcrest release. – rafalmag May 13 '12 at 19:34
  • @rafalmag Good spot. Will be good to fix all my not-so-readable assertions when v1.3 is released – andyb May 25 '12 at 15:33

5 Answers5

193

Well there's always

assertThat(list.isEmpty(), is(false));

... but I'm guessing that's not quite what you meant :)

Alternatively:

assertThat((Collection)list, is(not(empty())));

empty() is a static in the Matchers class. Note the need to cast the list to Collection, thanks to Hamcrest 1.2's wonky generics.

The following imports can be used with hamcrest 1.3

import static org.hamcrest.Matchers.empty;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.*;
Lance
  • 768
  • 7
  • 21
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 6
    I find that Hamcrest code looks much nicer if you change your syntax highlighting to make the parenthesis invisible... – skaffman Sep 02 '10 at 20:53
  • Your second assertThat() gives me the following error: The method assertThat(T, Matcher) in the type Assert is not applicable for the arguments (List, Matcher>) – Ian Dallas Sep 02 '10 at 21:12
  • 2
    @tkeE2036: That's Hamcrest's broken generics at work. Sometimes you need to cast to make it compile, e.g. `assertThat((Collection)list, is(not(empty())));` – skaffman Sep 02 '10 at 21:46
  • could you please give a link to `Matchers` class where this `empty()` method is defined? `org.hamcrest:hamcrest-all:1.1` doesn't have it. – yegor256 Apr 06 '11 at 15:51
  • @yegor256: Hamcrest is at v1.2 now. – skaffman Apr 13 '11 at 07:39
  • 1
    @skaffman : in this solution you still get compile warnings, because you do not use generics (and in fact you cant...) – rafalmag Jan 17 '12 at 13:07
  • 1
    Is this really easier to read than simply `assertFalse(list.isEmpty)`? I always believed DSL should remove boilerplate code instead of introducing it. – dzieciou Sep 30 '12 at 22:26
  • 14
    @dzieciou it gives you a better error message when the test fails. So instead of `expected true but got false` you get something like `expected empty but got [1, 2, 3]` – Brad Cupit Oct 22 '12 at 14:10
  • 3
    If you prefer no unchecked conversion, and are willing to give up the static import, then you can add the generics to the method, like: `assertThat(list, Matchers.empty())` (assuming list is a collection of `String`s) – earcam Jun 18 '13 at 03:03
  • Note that with the second `assertThat`, the test will pass if the list is `null`, so the test will assert the list is not empty when it actually is (well, actually it's null. There could be a long metaphysical discussion about if a null list can be considered empty, though) – Christian García Jul 10 '13 at 12:00
  • 2
    @Ian this answer is outdated and there are better answers that should be accepted now instead. –  Sep 15 '15 at 01:45
  • I would upvote this 1000 times if I could for the sole reason that unlike most Java answers, this answer actually includes the `import` statements you ***need*** to make the solution work. – meustrus Oct 01 '19 at 15:30
  • In kotlin you won't be able to use "is" since it's a reserved word. You need to use it between grave accents: `\`is\`` -> `\`is\`(not(empty())` – IIRed-DeathII Feb 21 '20 at 10:55
  • the lib is already fixed, use `assertThat(someList, not(empty()));` is enough – kelgwiin May 18 '20 at 15:08
85

This is fixed in Hamcrest 1.3. The below code compiles and does not generate any warnings:

// given
List<String> list = new ArrayList<String>();
// then
assertThat(list, is(not(empty())));

But if you have to use older version - instead of bugged empty() you could use:

hasSize(greaterThan(0))
(import static org.hamcrest.number.OrderingComparison.greaterThan; or
import static org.hamcrest.Matchers.greaterThan;)

Example:

// given
List<String> list = new ArrayList<String>();
// then
assertThat(list, hasSize(greaterThan(0)));

The most important thing about above solutions is that it does not generate any warnings. The second solution is even more useful if you would like to estimate minimum result size.

rafalmag
  • 1,791
  • 1
  • 17
  • 24
8

If you're after readable fail messages, you can do without hamcrest by using the usual assertEquals with an empty list:

assertEquals(new ArrayList<>(0), yourList);

E.g. if you run

assertEquals(new ArrayList<>(0), Arrays.asList("foo", "bar");

you get

java.lang.AssertionError
Expected :[]
Actual   :[foo, bar]
kamczak
  • 545
  • 5
  • 5
0

Create your own custom IsEmpty TypeSafeMatcher:

Even if the generics problems are fixed in 1.3 the great thing about this method is it works on any class that has an isEmpty() method! Not just Collections!

For example it will work on String as well!

/* Matches any class that has an <code>isEmpty()</code> method
 * that returns a <code>boolean</code> */ 
public class IsEmpty<T> extends TypeSafeMatcher<T>
{
    @Factory
    public static <T> Matcher<T> empty()
    {
        return new IsEmpty<T>();
    }

    @Override
    protected boolean matchesSafely(@Nonnull final T item)
    {
        try { return (boolean) item.getClass().getMethod("isEmpty", (Class<?>[]) null).invoke(item); }
        catch (final NoSuchMethodException e) { return false; }
        catch (final InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); }
    }

    @Override
    public void describeTo(@Nonnull final Description description) { description.appendText("is empty"); }
}
Community
  • 1
  • 1
0

This works:

assertThat(list,IsEmptyCollection.empty())
Richard
  • 188
  • 1
  • 5