Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does hamcrest say that a byte 0 is not equal to an int 0?

Tags:

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?

like image 564
sina Avatar asked Nov 26 '15 15:11

sina


People also ask

What are Hamcrest assertions?

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.

Why are there Hamcrest matchers?

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.

What is org Hamcrest matchers in?

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.

Why assertThat is deprecated?

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.


1 Answers

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.

like image 153
Sotirios Delimanolis Avatar answered Feb 24 '23 13:02

Sotirios Delimanolis