Consider the following test case using standard JUnit
asserts and hamcrest's assertThat
:
byte b = 0; int i = 0; assertEquals(b, i); // success assertThat(b, equalTo(i)); // java.lang.AssertionError: Expected: <0> but: was <0> if (b == i) { fail(); // test fails, so b == i is true for the JVM }
Why is that so? The values are apparently equal for the JVM because b == i
is true
, so why does hamcrest
fail?
Hamcrest is used for unit testing in Java. The goal of Hamcrest is to make it easier to read and write test cases. We use Hamcrest to write the matcher objects that allow us to define the match rules declarative.
Purpose of the Hamcrest matcher framework. Hamcrest is a widely used framework for unit testing in the Java world. Hamcrest target is to make your tests easier to write and read. For this, it provides additional matcher classes which can be used in test for example written with JUnit.
Hamcrest is the well-known framework used for unit testing in the Java ecosystem. It's bundled in JUnit and simply put, it uses existing predicates – called matcher classes – for making assertions.
assertThat method is deprecated. Its sole purpose is to forward the call to the MatcherAssert. assertThat defined in Hamcrest 1.3. Therefore, it is recommended to directly use the equivalent assertion defined in the third party Hamcrest library.
Assert#assertThat
is a generic method. Primitive types don't work with generics. In this case, the byte
and int
are boxed to Byte
and Integer
, respectively.
It then becomes (within assertThat
)
Byte b = 0; Integer i = 0; b.equals(i);
Byte#equals(Object)
's implementation checks if the argument is of type Byte
, returning false
immediately if it isn't.
On the other hand, assertEquals
is Assert#assertEquals(long, long)
in which case both the byte
and int
arguments are promoted to long
values. Internally, this uses ==
on two primitive long
values which are equal.
Note that this boxing conversion works because assertThat
is declared as
public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
where the byte
is boxed to a Byte
for T
, and the int
is a boxed to an Integer
(within the call to equalTo
), but inferred as a Number
to match the Matcher<? super T>
.
This works with Java 8's improved generic inference. You'd need explicit type arguments to make it work in Java 7.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With