axelhodler

assertEquals and assertThat

Hamcrest is a framework that assists in writing tests. The benefit of using Hamcrest is that the created assertions read more like written sentences and should help you to quickly grasp what a test is asserting.

In case you are wondering where the name comes from or what it has to do with ham: Hamcrest is an anagram of matchers.

Instead of using the assertEquals assertion you would use the assertThat assertion.

assertEquals("Frank", user.getName());
assertThat(user.getName(), is("Frank"));

Put into a sentence the first reads as:

assert equals frank username

While the latter reads as:

assert that username is frank

In my opinion the last one is easier and faster to understand.

Another difference you might have spotted is that the order of arguments has changed. While assertEquals uses the expected part as its first argument, assertThat is using the actual as its first.

With Hamcrest you will also get a different response when the test fails.

assertEquals("Peter", user.getName());

yields the following response:

org.junit.ComparisonFailure: expected:<[Peter]> but was:<[Frank]>

On the other hand:

assertThat(user.getName, is("Peter"));

leads to:

java.lang.AssertionError:
Expected: is "Peter"
     but: was "Frank"

I regard it as easier to compare the two strings vertically than horizontally. Especially when they become longer than just a few characters.

In case you are wondering what is actually does. It is just a wrapper that does not add any extra behavior to the underlying matcher. In case of using it like is("Frank") it’s actually doing is(equalTo("Frank")). The follow assertions are thus all equivalent.

assertThat(user.getName(), is("Frank"));
assertThat(user.getName(), equalTo("Frank"));
assertThat(user.getName(), is(equalTo("Frank")));

The are a lot more matchers that can be combined such as

assertThat(user.getName(), not(containsString("Professor")));

Check the documentation for more. If these are not enough you can also build your own custom matchers.

Hamcrest core ships with JUnit. Should your project already use JUnit, which i would regard as a must, you can get started with Hamcrest right away.

Addition on 21.11.2015

In the QA session of Three Test Automation Horror Stories, around the 25 min mark, Nat Pryce is asked about a common human error. He uses assertEquals as an example and that 50% of people use the actual output as the first argument of the method instead of the expected output. This will then lead to a faulty ComparisonFailure error message. The design of the assertEquals method is therefore considered error prone. This human error could easily be solved by using assertThat, where it is not possible to mix the two arguments.