How do I assert equality on two classes without an equals method?

java, junit, unit-testing

Solution

There is many correct answers here, but I would like to add my version too. This is based on Assertj.

import static org.assertj.core.api.Assertions.assertThat;

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .isEqualToComparingFieldByFieldRecursively(expectedObject);
    }
}

UPDATE: In assertj v3.13.2 this method is deprecated as pointed out by Woodz in comment. Current recommendation is

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .usingRecursiveComparison()
            .isEqualTo(expectedObject);
    }

}

Problem

Say I have a class with no equals() method, to which do not have the source. I want to assert equality on two instances of that class. I can do multiple asserts: ``` assertEquals(obj1.getFieldA(), obj2.getFieldA()); assertEquals(obj1.getFieldB(), obj2.getFieldB()); assertEquals(obj1.getFieldC(), obj2.getFieldC()); ... ``` I don't like this solution because I don't get the full equality picture if an early assert fails. I can manually compare on my own and track the result: ``` String errorStr = ""; if(!obj1.getFieldA().equals(obj2.getFieldA())) { errorStr += "expected: " + obj1.getFieldA() + ", actual: " + obj2.getFieldA() + "\n"; } if(!obj1.getFieldB().equals(obj2.getFieldB())) { errorStr += "expected: " + obj1.getFieldB() + ", actual: " + obj2.getFieldB() + "\n"; } ... assertEquals("", errorStr); ``` This gives me the full equality picture, but is clunky (and I haven't even accounted for possible null problems). A third option is to use Comparator, but compareTo() will not tell me which fields failed equality. Is there a better practice to get what I want from the object, without subclassing and overridding equals (ugh)?

Original source

Related problems