Friday, July 20, 2012

Hamcrest Matchers

Hamcrest matchers have been available for some time now, but I still don't see them being used regularly on projects. If you're not familiar with them, they are set of matchers that can be used with JUnit's assertThat syntax to make assertions easier to read and easier to diagnose when there are errors. Consider a test where we want to test if an object is a string. A traditional JUnit assertion might look like
Object o; // assume this is set during the test)
...
assertTrue(o instanceof String);
The default failure message is AssertionError. I could make the error message more meaningful by adding an error message (this still won't work if o is null).
assertTrue("expected String but was " + o.getClass(), o instanceof String);
Hamcrest matchers take of this for us. The assertion can be rewritten as
assertThat(o,is(instanceOf(String.class)));
Now the error message is java.lang.AssertionError: Expected: an instance of java.lang.String got: <4%gt;. Note the is is just syntactic sugar and is optional. Hamcrest matchers also help to resolve the ambiguity between the expected and equals parameters. A typical assertion for comparing two strings might look like:
assertEquals(expected,actual);
The assertEquals method is easy to get wrong and reverse the actual expected, which will produce backwards error messages. Using the hamcrest matchers, rewrite this is
assertThat(actual, equals(expected))
All hamcrest matchers follow this pattern of assertThat(actual, matcher), which make them read fluently. More information about hamcrest matchers can be found http://code.google.com/p/hamcrest/wiki/Tutorial. If you're writing Java unit tests, these provide a nice addition to the library.

No comments:

Post a Comment