java - matchers - ¿Por qué hamcrest dice que un byte 0 no es igual a un int 0?
import static org hamcrest corematchers containsstring (2)
Considere el siguiente caso de prueba utilizando aserciones de JUnit estándar y aseveración de 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
}
¿Por qué es así? Los valores son aparentemente iguales para JVM porque b == i es true , entonces ¿por qué falla hamcrest ?
Esto sucede porque el int y el byte están encajonados en Integer y Byte ya que los comparadores de hamcrest operan en objetos, no en primitivos. Entonces, estás comparando un Integer con un Byte , y la implementación de Byte.equals() es:
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
y Integer.equals() :
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
En otras palabras, un Integer y un Byte son siempre desiguales. Cuando se comparan primitivas, solo use Assert.assertEquals en Assert.assertEquals lugar. Los comparadores de hamcrest son poderosos, pero en su mayoría están destinados a aserciones de objetos (complejos).
Assert#assertThat es un método genérico. Los tipos primitivos no funcionan con los genéricos. En este caso, el byte y el int se encajonan en el Byte y el Integer , respectivamente.
Entonces se convierte (dentro de assertThat )
Byte b = 0;
Integer i = 0;
b.equals(i);
Byte#equals(Object) la implementación de Byte#equals(Object) verifica si el argumento es de tipo Byte , devolviendo false inmediatamente si no lo es.
Por otro lado, assertEquals es Assert#assertEquals(long, long) en cuyo caso los argumentos byte e int se promueven a valores long . Internamente, esto usa == en dos valores long primitivos que son iguales.
Tenga en cuenta que esta conversión de boxeo funciona porque assertThat se declara como
public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
donde el byte está encuadrado en un Byte para T , y el int es un recuadro en un Integer (dentro de la llamada a equalTo ), pero se infiere como un Number para coincidir con el Matcher<? super T> Matcher<? super T> .
Esto funciona con la inferencia genérica mejorada de Java 8. Necesitaría argumentos de tipo explícito para que funcione en Java 7.