Writing Hamcrest Matchers

JUnit 4 introduced a fancy DSL based on the Hamcrest framework for expressing assertions. JUnit ships with the most important matchers and you can always add Hamcrest to your classpath if you need more. Sometimes no existing matcher fits your needs and you have to roll your own. Since it’s not entirely obvious from the documentation, I’ll show a template for creating a simple Hamcrest matcher.

A check in JUnit 4 always looks something like this:

 
assertThat(actual, predicateName(expected));

The predicateName() factory method is just syntactic sugar, so let’s instantiate the matcher directly to make it more obvious what happens here:

 
assertThat(actual, new SomeMatcher(expected));

The first argument is of type ActualType, the expectation’s type (the constructor’s argument) is ExpectedType. This is our implementation of SomeMatcher:

 
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.TypeSafeMatcher;
 
public class SomeMatcher extends TypeSafeMatcher<ActualType> {
    private final ExpectedType expected;
 
    public SomeMatcher(ExpectedType expected) {
        this.expected = expected;
    }
 
    @Override
    public boolean matchesSafely(ActualType actual) {
        // return true iff "actual" matches "expected"
    }
 
    @Override
    public void describeTo(Description descr) {
        // describe expectation
    }
 
    @Factory
    public static SomeMatcher predicateName(ExpectedType expected) {
        return new SomeMatcher(expected);
    }
}

The @Factory annotation isn’t necessary, but Hamcrest ships with a tool that picks up predicates annotated this way and collects them in a Matchers class for easy importing.

Advertisements
This entry was posted in java and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s