为什么hamcrest说字节0不等于int 0?

时间:2015-11-26 15:06:07

标签: java junit hamcrest

使用标准JUnit断言和hamcrest的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
}

为什么会这样? JVM的值明显相等,因为b == itrue,为什么hamcrest会失败?

2 个答案:

答案 0 :(得分:28)

Assert#assertThat是一种通用方法。原始类型不适用于泛型。在这种情况下,byteint分别被设置为ByteInteger

然后变为(assertThat内)

Byte b = 0;
Integer i = 0;

b.equals(i);

Byte#equals(Object)的实现检查参数是否为Byte类型,如果不是,则立即返回false

另一方面,assertEqualsAssert#assertEquals(long, long),在这种情况下,byteint参数都会提升为long个值。在内部,它在两个相等的原始==值上使用long

请注意,此装箱转换有效,因为assertThat声明为

public static <T> void assertThat(T actual, Matcher<? super T> matcher) {

其中byteByte T加为int,而Integer被加框为equalTo(在Number的调用中1}}),但推断为Matcher<? super T>以匹配class ApplicationController < ActionController::Base protect_from_forgery with: :exception # Devise Authentication, included this line because I know Devise messes # with CSRF token and I'd be appreciate expert opinion on how my solution will 'play' with devise before_action :authenticate_user! # callback to set CSRF TOKEN for non-idempotent ajax request after_action :add_csrf_token_to_json_request_header private def add_csrf_token_to_json_request_header if request.xhr? && !request.get? && protect_against_forgery? response.headers['X-CSRF-Token'] = form_authenticity_token end end end

这适用于Java 8改进的通用推理。您需要显式类型参数才能使其在Java 7中运行。

答案 1 :(得分:13)

这是因为intbyte被装箱到IntegerByte,因为hamcrest匹配器对对象进行操作,而不是对基元进行操作。因此,您要将IntegerByte进行比较,Byte.equals()的实施是:

public boolean equals(Object obj) {
    if (obj instanceof Byte) {
        return value == ((Byte)obj).byteValue();
    }
    return false;
}

Integer.equals()

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

换句话说,IntegerByte总是不相等的。比较基元时,只需使用Assert.assertEquals。 hamcrest匹配器功能强大,但主要用于(复杂)对象断言。