Testing the equals method
When testing Java classes, a common requirement is that the equals(Object) method works properly. When using JUnit, this can be as simple as:
import static org.junit.Assert.*; : assertEquals(a, b);
However, you may want to test that not only a
considers itself equal to b
but also vice versa. With a single assertEquals
call this won’t work, so you add:
assertEquals(b, a);
Perfect, right?
Possibly. What if the test fails? How do you determine what the equals
method actually considers a difference? The comparison algorithm can be quite complex, involving several instance fields, including collections, maps and XML snippets.
Differences for humans
It would help if the class would describe the differences in a human-readable manner. Here’s how: Declare an interface VerboseDiff
(or whatever better name you can come up with) with just one method that describes the differences between this object and the specified argument. It returns null
if there are no differences:
public interface VerboseDiff { String describeDifferences(Object obj); }
Then change your implementation classes to implement this interface and implement the equals
method as follows:
@Override public boolean equals(Object obj) { return describeDifferences(obj) == null; }
Your describeDifferences
method could be implemented as follows:
public String describeDifferences(Object obj) { if (obj == null)) { return "obj == null"; } else if (! (obj instanceof ThisClass)) { return "obj is not an instance of ThisClass, but an instance of class " + obj; } ThisClass that = (ThisClass) obj; if (that._baseValue != _baseValue) { return "baseValue of this object (" + _baseValue + ") is different from base value of argument (" + baseValue + ')'; } return null; }
Now your unit tests can look like this:
assertEquals(null, a.describeDifferences(b)); assertEquals(null, b.describeDifferences(a));
Further reading
A final tip: Implementing a good comparison algorithm that is in line with the contract of the equals
method is typically not straight-forward, especially if you need to deal with subclasses. The article How to Write an Equality Method in Java (at artima.com) covers the topic excellently.