FAQ
Philosophy
Can EqualsVerifier give false positives?
Yes, it can. EqualsVerifier will not search a class’s entire state space. If you write an equals
method as below, EqualsVerifier will not notice that it’s incorrect.
The example is a little far-fetched, but it illustrates the point that you have to write bad code on purpose to make EqualsVerifier think your equals
method is correct when it is not.
Can EqualsVerifier give false negatives?
Yes, it can. Just try to verify String
: it will fail. String
employs some tricks for better performance, that EqualsVerifer can’t verify. However, the good people who wrote String
knew what they were doing, and have formally proven their implementation correct. If you have a formal proof that your implementation is correct, you don’t need EqualsVerifier.
So what’s the point of EqualsVerifier then?
EqualsVerifier is a useful tool for anyone who wants to implement the equals
and hashCode
methods, without trying anything fancy. Implementing equals
is hard, even for simple classes. Since most classes are simple, EqualsVerifier can be a great help in making sure that your implementation fulfills the contract.
EqualsVerifier catches common mistakes, such as forgetting to include a field in hashCode
that is tested in equals
. It also encourages robustness, for example by warning about non-final fields, and by watching out for inheritance issues.
If you run into a situation where EqualsVerifier can’t help you, you are probably in one (or more) of the following situations:
- You’re writing non-trivial, high-performance niche code at NASA.
- You’re a Java API developer.
- You’re writing malicious code on purpose.
- You’re writing code that’s way too complicated, and you should probably refactor.
(And even in the first two cases, EqualsVerifier can help creating an initial working implementation.)
How should I write a good equals
method?
By far the best explanation on the subject, in my opinion, can be found in Chapter 28 of Programming in Scala by Martin Odersky, Bill Venners and Lex Spoon. The authors have adapted the chapter to Java and placed it online here.
Another excellent source, of course, is Items 8 and 9 from Josh Bloch’s Effective Java, Second Edition.
See the manual page about inheritance if you want to use the canEqual
method described by Odersky et al.
Does EqualsVerifier give me 100% code coverage?
Yes, it does. EqualsVerifier’s test suite contains a collection of many different common implementation patterns of equals
and hashCode
, including those generated by IntelliJ IDEA, Eclipse, Netbeans and Project Lombok, which are all tested for 100% code coverage by JaCoCo.
Of course, there are many ways to implement equals
, and despite my efforts, it’s possible that ‘I missed a spot’. See this page for more information on what to do when you find such a case.
Error messages
Can you explain the error message I just got from EqualsVerifier?
Sure! Just take a look at the Error Messages page.
I’m testing java.lang.String
, but it fails.
Please don’t test java.lang.String
, because indeed it fails. Please see the section on false negatives above.
Why did you remove #forExamples
?
At first, the main raison-d’être for #forExamples
was that I wasn’t sure I could make #forClass
work for under all circumstances. By EqualsVerifier 1.0, I was convinced that I could, but by then a lot of people were already using it.
Later, I (and other users) started noticing it could cause some hard-to-debug problems, so version 2.0 seemed like a good moment to clean up the API and remove it.
The issues that #forExamples
caused, mainly had to do with static values. As part of the verification process, EqualsVerifier will assign values to all fields of the class under test, including static fields (but not static final fields). These values are unpredictable, may break your class invariants, and may even be invalid under normal conditions. If you used EqualsVerifier.forExamples
, and you re-used the instances of the class under test, this could impact other tests that also used these instances and expected them to have different values.
Build
How do I build EqualsVerifier?
First, check out the code. You can open the project in Eclipse or IntelliJ, or you can run Maven from the command-line. Note that Java 7 or higher is required to compile the project.
I get generics errors while building
type parameters of <S>S cannot be determined; no unique maximal instance exists for
type variable S with upper bounds T,java.lang.Object
EqualsVerifier makes heavy use of generics. Sun’s Java compiler has a known bug regarding generics. Since I use Eclipse and OpenJDK, which do not exhibit this bug, it’s possible I write code that triggers the bug, and the code might not compile. If this happens, please let me know in an issue and I’ll fix it.