为什么 junit return 中的 assertEquals 和 assertSame 对于两个实例相同 class 的结果相同?

Why assertEquals and assertSame in junit return the same result for two instances same class?

根据文档

assertEquals() Asserts that two objects are equal.

assertSame() Asserts that two objects refer to the same object.

所以我希望如果我有一个像下面这样的 class

class SomeClass {}

然后

SomeClass someClass1= new SomeClass();
SomeClass someClass2= new SomeClass();
assertSame(someClass1,someClass2); // fail
assertEquals(someClass1,someClass2); // fail

assertEquals 应该通过而 assertSame 应该失败,因为两个 classes 的值相等但它们具有不同的引用位置。

因为我在这两种情况下都失败了,所以我的问题是这两者之间有什么区别?

assertEquals 使用 equals() 方法(你应该在你的 class 中覆盖它来真正比较它的实例)来比较对象,而 assertSame 使用 == 运算符来比较它们。所以区别与==(按值比较)和equals(比较身份)完全相同。

由于您没有在 class 中覆盖 equals,assertEquals 的行为与 assertSame 相同,因为默认 equals 实现比较引用。

150    public boolean equals(Object obj) {
151        return (this == obj);
152    }

如果您提供一个愚蠢的等于覆盖:

class SomeClass {
    @Override 
    public boolean equals(Object o) {
        return true;
    }
}

你会看到 assertEquals 成功了。

第一个断言失败,因为 someClass1sameClass2 不是同一个实例。第二个断言失败,因为 equals(Object) 方法尚未在 SomeClass 中定义,并且它的超 equals(Object) 引用相等。由于比较两个不同的实例是否相等,所以这个失败的原因与第一个相同。

官方 JUnit 文档:

assertEquals: Asserts that two objects are equal.

assertSame: Asserts that two objects refer to the same object.

换句话说

assertEquals: uses the equals() method, or if no equals() method was overridden, compares the reference between the 2 objects.

assertSame: compares the reference between the 2 objects.

示例 1:equals 方法 未被 覆盖,因此 assertSame 和 assertEquals return 结果相同,因为它们比较对象的引用。

public class A {    
    private int i;
    public A(int i){ this.i = i; }
}

public class TestA {
    final A a1 = new A(0);
    final A a2 = new A(0);

    @Test
    public void assertsame_testAssertSame(){
        assertSame(a1, a2); // AssertionError: expected:<test2.A@7f13d6e> but was:<test2.A@51cdd8a>
    }

    @Test
    public void assertsame_testAssertEquals(){
        assertEquals(a1, a2); // AssertionError: expected:<test2.A@7f13d6e> but was:<test2.A@51cdd8a>
    }
}

例2: equals方法被覆盖,所以assertSame和assertEquals return结果不一样,因为这次assertEquals会用到equals方法

public class A {
    private int i;
    public A(int i){ this.i = i; }

    @Override
    public boolean equals(Object o){
        // self check
        if(this == o){ return true; } else
        // null check
        if(o == null){ return false;} else
        // type check and cast
        if(getClass() != o.getClass()){ return false; } else {
            final A a = (A) o;
            // field comparison
            return Objects.equals(a, a);
        }
    }
}
public class TestA {
    final A a1 = new A(0);
    final A a2 = new A(0);

    @Test
    public void assertsame_testAssertSame(){
        assertSame(a1, a2); // AssertionError: expected:<test2.A@7f13d6e> but was:<test2.A@51cdd8a>
    }

    @Test
    public void assertsame_testAssertEquals(){
        assertEquals(a1, a2); // OK
    }
}

assertEquals: ==
断言相同:===

'same' 匹配类型以及与'==='相同的值。

assertEquals - 它根据 class 的重写 equals() 方法检查对象是否相等。所以我们可以根据它们的状态来检查对象的相等性(比较它们的实例变量的值)。

assertEquals() assertEquals() 方法比较两个对象是否相等,使用它们的 equals() 方法。

@Test
public void assertEquals_example() {
    Employee employeeNew = new Employee();
    employee.setSalary(1000000.0);
    assertEquals("EMPLOYEE OBJECT", employee, employeeNew);
}

如果根据 equals() 方法的实现,两个对象相等,则 assertEquals() 方法将正常 return。否则,assertEquals()方法会抛出异常,测试就此停止。

assertSame() 和 assertNotSame() assertSame() 和 assertNotSame() 方法测试两个对象引用是否指向同一个对象。根据它们的 equals() 方法,仅仅指向两个对象相等是不够的。它必须与指向的对象完全相同。

这是一个简单的例子:

@Test
public void assertSame_assertNoSame_example() {

    assertSame(employeeService.getEmployeeFromId(1), employeeService.getEmployeeFromId(1));
    assertNotSame(employee, employeeService.getEmployeeFromId(1)); // We will get null as response
}