≡ Menu

Unit Testing Equals and HashCode of Java Beans

We’ve been creating several Java Beans that have an imperative need to have both equals and hashCode working correctly. To do this, we started off writing a series of test cases which made sure that for every field we exposed that the objects were / were not equal based on if the field was set, and that the field was taken into account as part of the hashCode calculation. After doing two of these, I figured there had to be a better way, and after some research, ended up writing a BeanTestCase class which exposes an assertMeetsEqualsContract method and an assertMeetsHashCodeContract method. Note that while there are projects out there (like Assertion Extensions for JUnit) that have assertions for equals and hashCode, they don’t actually walk the fields of the objects and test the various scenarios of changing each field.

After I had written this, I applied it to classes we already had unit tests for around equals and hashCode – and immediately found a bug in one of the classes where we missed a field. That paid for itself right away. ;)

Being that I’m just getting back into the Java world, if there are better ways, please let me know!

Comments on this entry are closed.

  • Substance January 26, 2009, 11:55 am

    Looks great, I’m gonna give it a try!

  • Robert Beltran March 13, 2009, 2:30 pm

    Awesome senor. You may have saved me like 3 hours of work. I will be sure to credit you in the source.

  • sebo July 11, 2009, 7:45 am

    You made amistake when you set o2 with double value in assertMeetsEqualsContract. There have to be 0 ;) (or something else than 1 ). But afterall it’s great job ;).

  • Benjamin Winterberg August 25, 2009, 3:45 pm

    This is really helpful, thanks. Supplements well with one of my last articles, how to effectivly implement equals(), hashCode(), compareTo() and toString():

    http://bwinterberg.blogspot.com/2009/08/building-equals-hashcode-compareto-and.html

  • StevenPN September 20, 2009, 4:41 am

    привет лунатикам!

  • Ramesh March 17, 2010, 8:35 pm

    The code won’t work if the class is having reference types :(

  • Iacopo February 9, 2012, 2:42 am

    Hi,
    I had to add the following lines:

    if (Modifier.isFinal(field.getModifiers() ))
    {
    continue;
    }

    In order to let it work with final fields. The lines were added before the field.getType() sequences of if(s)