Sunday, May 20, 2012

Hamcrest Matchers in JUnit tests

Normal assertions in JUnit would look like this:

Assert.assertEquals(expectedValue, actualValue); for example Assert.assertEquals(3, bean.getValue());

With hamcrest matchers, we can make the tests much more expressive and with recent versions of JUnit, core hamcrest matchers are bundled with JUnit and so there is no need to download and add hamcrest to our classpath explicitly.

JUnit has this new static method in org.junit.Assert called assertThat which has signature like this:

assertThat(actual, Matcher);

Using this, we can make the tests very expressive. First add some of the static imports:

import static;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;

Then, assertions can look like this:

      assertThat(bean.getValue(), is(equalTo(3)));
      assertThat(bean.toString(), is("XYZ"));
      assertThat(bean.getNewValue(), is(nullValue());
      assertThat(bean.getType(), is(not(nullValue()));

This shows how readable these tests are when compared to the regular assertions. Also, we can see that matchers can be nested. In the above block, is and not, is and equalTo, is and nullValue() are chained to make it more readable.

There are more matchers available in org.hamcrest.core package inside junit jar. In Eclipse, you can open up the junit jar under referenced libraries and navigate to this particular folder in package explorer to see other available matchers.

Only drawback that I found is, I cannot use assertThat for comparing double values with tolerance. Other than that, I tend to assertThat for most of my assertions. It certainly makes my tests much more readable and expressive!


Shubhashish Bhowmik said...

Nice Post. And thanks for information.

John Arthorne said...

I guess it's a matter of perspective, but I find assertEquals(3, bean.getValue()) is much more readable than the hamcrest version. The assertEquals function clearly takes two values and compares them. On the other hand when I see isEqualTo(3) I am very confused. How can a function with a single argument be comparing anything? Similarly is(not(nullValue())) is just a very convoluted way of expressing something that java has a built in operator for (x!=null).

teja ul said...

Very nice article.. In order to fulfill the ever changing requirements of our prestigious clients, we are offering a comprehensive range of Precision Machined Components you can refer Precision Machined Components

craige boyle said...

If you plan on a long term career as a project manager, then yes, even with your level of experience, I would suggest getting your PMP. You can prepare yourself for the exam in one of the PMP trainingproviders like You can do minimal prep-work to get 40 PMI® Contact Hours and apply to PMI for PMP Exam before the class begins.