- Error messages
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
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
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
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.
Can you explain the error message I just got from EqualsVerifier?
Sure! Just take a look at the Error Messages page.
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
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.
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.