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

71,737

Solution 1

Since you didn't override equals in your class, assertEquals behaves the same as assertSame since the default equals implementation compare references.

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

If you provide a dumb overriding of equals:

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

you'll see that assertEquals succeeds.

Solution 2

assertEquals uses equals() method (that you should override in your class to really compare its instances) to compare objects, while assertSame uses == operator to compare them. So the difference is exactly the same as between == (compare by value) and equals (compare identity).

Solution 3

Official JUnit documentation:

assertEquals: Asserts that two objects are equal.

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

In other words

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.

Example 1: equals method was not overridden, so assertSame and assertEquals return the same result, since they compare the objects' reference.

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>
    }
}

Example 2: equals method was overridden, so assertSame and assertEquals return the not same result, since the equals method will be used by assertEquals this time.

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
    }
}

Solution 4

assertEquals: ==
assertSame: ===

'same' matches the type along with the value which is the same as '==='.

Share:
71,737
rawData
Author by

rawData

Updated on May 11, 2020

Comments

  • rawData
    rawData almost 4 years

    According to documentation

    assertEquals() Asserts that two objects are equal.

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

    So I am expecting that if I have a class like below

    class SomeClass {}
    

    then

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

    the assertEquals should pass and assertSame should fail, as the value of both classes are equal but they have different reference location.

    As I get failure in both cases then my question is what are the difference between these two ?