Почему assertEquals и assertSame в junit возвращают одинаковый результат для двух экземпляров одного класса?

Согласно документации

assertEquals() Утверждает, что два объекта равны.

assertSame() Утверждает, что два объекта ссылаются на один и тот же объект.

Так что я ожидаю, что если у меня будет класс, как показано ниже

class SomeClass {}

затем

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

assertEquals должен пройти, а assertSame должен завершиться ошибкой, так как значения обоих классов равны, но они имеют разное ссылочное местоположение.

Поскольку в обоих случаях я получаю провал, возникает вопрос: в чем разница между этими двумя?

Ответ 1

Поскольку вы не переопределили равные в своем классе, assertEquals ведет себя так же, как assertSame, поскольку значение по умолчанию равно сравнению с ссылками сравнения реализации.

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

Если вы обеспечиваете немое переопределение равных:

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

вы увидите, что assertEquals преуспевает.

Ответ 2

assertEquals использует метод equals() (который вы должны переопределить в своем классе, чтобы действительно сравнить его экземпляры) для сравнения объектов, а assertSame использует оператор == для их сравнения. Таким образом, разница точно такая же, как между == (по значению) и equals (сравните идентификатор).

Ответ 3

Официальная документация JUnit:

assertEquals: утверждает, что два объекта равны.

assertSame: утверждает, что два объекта относятся к одному и тому же объекту.

Другими словами

assertEquals: использует метод equals(), или если метод equals() не был переопределен, сравнивает ссылку между двумя объектами.

assertSame: сравнивает ссылку между двумя объектами.

Пример 1: метод equals был не переопределен, поэтому assertSame и assertEquals возвращают тот же результат, поскольку они сравнивают ссылку на объекты.

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:<[email protected]> but was:<[email protected]>
    }

    @Test
    public void assertsame_testAssertEquals(){
        assertEquals(a1, a2); // AssertionError: expected:<[email protected]> but was:<[email protected]>
    }
}

Пример 2: метод equals переопределен, поэтому assertSame и assertEquals возвращают не тот же результат, так как на этот раз метод equals будет использоваться assertEquals.

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:<[email protected]> but was:<[email protected]>
    }

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

Ответ 4

Первое утверждение терпит неудачу, потому что someClass1 и sameClass2 - не те же экземпляры. Второе утверждение терпит неудачу, потому что метод equals(Object) не был определен в SomeClass, а его супер equals(Object) ссылается на равенство. Так как два разных экземпляра сравниваются для равенства, это происходит по той же причине, что и первая.

Ответ 5

assertEquals - Он проверяет, что объекты равны или не основаны на переопределенном методе equals() этого класса. Таким образом, мы можем проверить равенство объектов в зависимости от их состояния (сравнить значения переменных их экземпляров).

assertEquals() Метод assertEquals() сравнивает два объекта на равенство, используя их метод equals().

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

Если два объекта равны в соответствии с реализацией их метода equals(), метод assertEquals() будет возвращаться нормально. В противном случае метод 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
}

Ответ 6

assertEquals: ==
assertSame: ===

"same" соответствует типу вместе со значением, которое совпадает с "===".