I like my tests to be elegant and self-reading. Thus I like Hamcrest, of course. For those of you, who don’t know Hamcrest: It’s an addition to JUnit that makes your code to be read like a sentence:
The advantage of such test are not only that they can be read like sentences, but also that they produce self-explaining error messages without writing one character of description. I.e. when you change the last line of the example to
the resulting error message is ‚Expected a collection containing „baz“, but was [„foo“, „bar“]‘ which explains pretty clearly what the problem is.
This does not only work for collections, but also for your own objects and their properties:
which would lead to ‚Expected is null, but was „bar“‚ when you return „bar“ instead of the expected null. Even in this case you can guess the problem from the error message, even when it doesn’t work as well as in the collection case.
Error messages become totally useless, when it comes to boolean assertions. I.e.
would lead to ‚Expected is <true>, but was <false>‘ and you don’t have a clue of what went wrong. You can improve the error messages by using the ‚hasProperty‘ matcher like
which leads to ‚Expected hasProperty(„bar“, is <true>) but property ‚bar‘ was <false>“. The message is somewhat readable, but the code to get there is horrible, because it is not really readable any more plus we totally lose type-safety which sooner or later would lead to failing tests due to refactoring.
Having this problem, I came up with an idea how to extend JUnit to support self-explaining boolean assertions. With my tiny extension the above code looks like
and, when bar returns false, the error message reads like: ‚Expected result of method isBar expected <true> but was <false>‘. The other way round would look like
With this extension I get readable code and explaining error messages. How did I achieve this? My tiny little JUnit extension is written with the help of cglib (2.1_3) and fits in one class:
The first method just delegates to Hamcrest’s assertThat and is needed just to support static imports of ‚classic‘ assertThat in JUnit-Tests. I hope this post helps you to write elegant and self-reading tests.