assertThat

I’ve just found a new feature in junit 4.4: assertThat()1. This gives you a much nicer way of specifying assertions than the usual assertEquals() or assertTrue(). Some examples from the docs above:

  assertThat(x, is(3));
  assertThat(x, is(not(4)));
  assertThat(responseString, either(containsString("color")).or(containsString("colour")));
  assertThat(myList, hasItem("3"));

This is both very readable, and leads to much improved diagnostic messages in failure.

It’s also (relatively) easy to extend to provide your own matchers (although check out hamcrest for some handy predefined ones). For example, I’ve just come up with this class to assert whether a collection is empty is empty or not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class EmptyMatcher extends TypeSafeMatcher<Collection<?>> {
    @Override
    public boolean matchesSafely(Collection<?> c) {
        return c.isEmpty();
    }
 
    public void describeTo(Description desc) {
        desc.appendText("empty");
    }
 
    @Factory
    public static <T> Matcher<? super Collection<?>> empty() {
        return new EmptyMatcher();
    }
}

This is based on the example in the hamcrest tutorial. The only thing of real interest is the static factory method empty()2. This is what you would import static, so you can say:

  assertThat(setOfThings, empty());

This is more concise and leads to better error reporting than it’s predecessor.

  assertThat(setOfThings.size(), is(0));

One of the other nice things about using Matchers is that you can have side effects other than matching something. A great example is describedAs(). Say that you have:

  assertThat(a.getFrog(), is(not(nullValue())));

This would produce an error like:

Expected: is not null
Got: null

You can add in a description like this:

  assertThat(a.getFrog(), describedAs("frog", is(not(nullValue()))));

The error now becomes:

Expected: frog
Got: null

In the use I’ve put it to so far, this seems to be particularly appropriate for null values, which are otherwise quite unhelpful when a test fails.

I’ve completely switched my latest project to using assertThat(). So far, it seems to be leading to some nice readable code and I’m quite pleased with the results.

1 As an aside, “junit.org FAIL”: no javadocs, no news. The place is a mess.

2 I recommend checking out the chapter on generics in Effective Java 2nd Edition in order to properly understand the declaration here.

Comments are Closed