Почему 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" соответствует типу вместе со значением, которое совпадает с "===".