Technique to automatically check consistency of equals, hashCode, and compareTo?
Asked Answered
C

5

20

I'm well aware of the contractual needs to make sure that hashCode is consistent with equals and that equals is consistent with compareTo. However, this is often violated in practice. Are there any tools, techniques, or libraries that can test for this consistency automatically?

I suspect unfortunately that the answer is "no," but it would be useful to be able to have a unit test for this sort of thing that could make use of a library call or framework rather than needing to write a custom test by hand for each case where it is important.

In case it's not clear what I mean by consistency, for hashCode and equals I refer to the following:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

For equals and compareTo I refer to the following:

The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C.

Carisa answered 8/3, 2012 at 20:1 Comment(2)
Just stick a few objects into a HashMap and a TreeMap and see if you can get them back ;-)Subdiaconate
See also: #10633504Heroworship
R
12

Guava's tests have a utility called EqualsTester which we use as an everyday part of our unit tests to test equals and hashCode. Its use looks like

new EqualsTester()
  .addEqualityGroup("hello", "h" + "ello")
  .addEqualityGroup("world", "wor" + "ld")
  .addEqualityGroup(2, 1 + 1)
  .testEquals();

which tests that all values in the same group are equal and have the same hash codes, that different groups are not equal, and that various other invariants are all satisfied. You could either use it yourself, or just borrow its ideas.

I would be extremely surprised if it was possible to test without generating or explicitly specifying test values, just because that seems very likely equivalent to the halting problem.

Reverberation answered 8/3, 2012 at 20:12 Comment(0)
C
5

If you're using JUnit, the extensions package has the EqualsHashCodeTestCase, which fully tests both equals and hashCode for everything outlined in the Java spec (reflexive, transitive, symmetric, etc). All you have to do is provide an equal and not equal object for the parent class to use for checking.

Since the CompareTo method is part of the Comparable interface, it's actually split out into another test case - the ComparabilityTestCase. This takes three objects - one of lesser value, equal value, and greater value. Override these and the parent class will take care of the rest.

Colorful answered 12/2, 2013 at 18:19 Comment(1)
This looks promising. When I get around to investigating them, if they do what I think they do then you'll likely earn a green checkmark from me.Carisa
A
1

I have written some utility methods to help unit testing hashCode and equals methods:

http://softsmithy.sourceforge.net/devlib/docs/api/org/softsmithy/devlib/junit/Tests.html

The library is Open Source and can be downloaded from here: http://sourceforge.net/projects/softsmithy/files/softsmithy-devlib/v0.1/

or with Maven:

    <dependency>
        <groupId>org.softsmithy.devlib</groupId>
        <artifactId>devlib-core</artifactId>
        <version>0.1</version>
        <scope>test</scope>
    </dependency>
Asceticism answered 8/3, 2012 at 20:15 Comment(0)
C
1

There is a very cool tool called Korat that can do exhaustive searches to check the correctness of Java classes for small cases. It actually looks at the code that's executed in order to build all the different test cases of a given size that the program can actually distinguish between. I don't know how useful it is in large cases, but for many programs it can be used to automatically check whether cases like this work correctly.

Hope this helps!

Combustion answered 8/3, 2012 at 20:35 Comment(1)
You liked a paper about Korrat. The Korrat homepage is: korat.sourceforge.netHeroworship
B
1

I’ve recently used meanbean (http://meanbean.sourceforge.net/) to automatically test a class for the equals() and hashCode() contracts (plus setter/getter pairs).

"Mean Bean:

1. Tests that the getter and setter method pairs of a JavaBean/POJO function correctly. 2. Verifies that the equals and hashCode methods of a class comply with the Equals Contract and HashCode Contract respectively. 3. Verifies property significance in object equality."

I still have a lot of questions specific to meanbean: whether it verifies equals() and hashCode() consistency. Plus I haven’t tried hard to defeat it. I believe it has no support for compareTo(). And I haven’t tried alternatives. Interested in other's experience.

Bosh answered 9/11, 2012 at 16:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.