The EqualsVerifier library may be used in Java unit tests to automatically verify equals()
implementations and provides one hundred percent code coverage on equals()
and hashCode()
methods. Recent releases have improved support for the Java Persistence Architecture and Jakarta Persistence specification (JPA), by requiring the use of getters instead of fields, and solving several related bugs.
Version 3.15 introduced a breaking change as it requires using getters inside the equals()
method for all mapped fields in JPA entities such as @OneToMany
and @ManyToOne
. The requirement is independent of using the FetchType.LAZY
or FetchType.EAGER
strategies, as in some cases even eager fields may be null
. The new behavior can be disabled with suppress(Warning.JPA_GETTER)
in case it's not desired. More details may be found in the JPA entities chapter of the manual.
Version 3.15.1 resolved an error which was thrown when the getter method of an unused mapped field in a JPA entity wasn’t used in the equals()
and hashCode()
methods. Version 3.15.2 resolved an error which was thrown when the hashCode()
method didn’t use all fields of a JPA entity, despite suppressing Warning.STRICT_HASHCODE
.
The 3.15 release also introduced the new withFieldnameToGetterConverter()
method which allows a custom derivation of getter names from field names, in case they differ.
EqualsVerifier may be used after adding the following Maven dependency:
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
<version>3.15.2</version>
<scope>test</scope>
</dependency>
Alternatively, a fat jar without transitive dependencies may be used:
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier-nodep</artifactId>
<version>3.15.2</version>
<scope>test</scope>
</dependency>
The following Student
class provides an equals()
method:
class Student {
private String firstName;
private String lastName;
public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Student student)) {
return false;
}
return firstName == student.firstName &&
lastName == student.firstName;
}
}
EqualsVerifier may be used in a JUnit test in order to verify the implementation of the equals()
method in the Student
class:
private String expectedErrorMessage = """
EqualsVerifier found a problem in class
com.example.EqualsVerifierTest$Student.
-> hashCode: hashCodes should be equal:""";
@Test
public void testStudentEquals() {
AssertionError assertionError =
Assertions.assertThrows(AssertionError.class, () -> {
EqualsVerifier.forClass(Student.class).verify();
});
assertTrue(assertionError.getMessage()
.startsWith(expectedErrorMessage));
}
An assertion is thrown as the equals()
method isn't correct.
The issues may be resolved by adding the final
keyword to the firstName
and lastName
fields and the equals()
method. After that, correct implementations for the equals()
and hashcode()
methods should be provided:
class FixedStudent {
private final String firstName;
private final String lastName;
public FixedStudent(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FixedStudent)) return false;
FixedStudent that = (FixedStudent) o;
return Objects.equals(firstName, that.firstName) &&
Objects.equals(lastName, that.lastName);
}
@Override
public final int hashCode() {
return Objects.hash(firstName, lastName);
}
}
EqualsVerifier can now be used to verify that the equals()
method of the FixedStudent
class is correct:
@Test
public void testFixedStudentEquals() {
Assertions.assertDoesNotThrow(() -> {
EqualsVerifier.forClass(FixedStudent.class).verify();
});
}
Jan Ouwens, senior software developer at Yoink! created EqualsVerifier and maintains a website with more information, including a detailed manual. Tom Cools, software developer at Info Support, created a short introduction video to teach the basics of EqualsVerifier. The GitHub changelog lists all the recent releases and their respective changes.