自动检查equals,hashCode和compareTo的一致性的技巧?

时间:2012-03-08 20:01:16

标签: java unit-testing equals hashcode compareto

我非常了解合同需求,以确保hashCodeequals一致且equalscompareTo一致。但是,这是often violated in practice。是否有任何工具,技术或库可以自动测试这种一致性?

我怀疑不幸的是答案是"不,"但是能够对这种可以使用库调用或框架的东西进行单元测试是有用的,而不是需要为每个重要的情况手动编写自定义测试。

如果不清楚我的一致性是什么意思,对于hashCodeequals,请参阅以下内容:

  

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.

对于equalscompareTo,请参阅以下内容:

  

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.

5 个答案:

答案 0 :(得分:12)

Guava's测试有一个名为EqualsTester的实用程序,我们将其用作单元测试的日常部分,以测试equalshashCode。它的用途看起来像

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

测试同一组中的所有值相等且具有相同的哈希码,不同的组相等,并且各种其他不变量都满足。你可以自己使用它,也可以借用它的想法。

如果可以在不生成或明确指定测试值的情况下进行测试,我会非常惊讶,因为这似乎非常可能等同于暂停问题。

答案 1 :(得分:5)

如果您正在使用JUnit,则扩展包具有EqualsHashCodeTestCase,它完全测试了Java规范(自反,传递,对称等)中概述的所有内容的equals和hashCode。您所要做的就是为父类提供一个相等且不相等的对象来进行检查。

由于CompareTo方法是Comparable接口的一部分,它实际上被拆分为另一个测试用例 - ComparabilityTestCase。这需要三个对象 - 一个较小的值,相等的值和更大的值。覆盖这些,父类将负责其余的工作。

答案 2 :(得分:1)

我编写了一些实用工具方法来帮助单元测试hashCode和equals方法:

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

该库是开源的,可以从这里下载: http://sourceforge.net/projects/softsmithy/files/softsmithy-devlib/v0.1/

或与Maven:

    <dependency>
        <groupId>org.softsmithy.devlib</groupId>
        <artifactId>devlib-core</artifactId>
        <version>0.1</version>
        <scope>test</scope>
    </dependency>

答案 3 :(得分:1)

有一个非常酷的工具叫做 Korat ,它可以进行详尽的搜索,以检查小类的Java类的正确性。它实际上是查看为了构建程序实际可以区分的给定大小的所有不同测试用例而执行的代码。我不知道它在大型案件中有多大用处,但对于许多程序,它可以用来自动检查这样的案例是否正常工作。

希望这有帮助!

答案 4 :(得分:1)

我最近使用meanbean(http://meanbean.sourceforge.net/)自动测试equals()和hashCode()契约的类(加上setter / getter对)。

“Mean Bean:

1.测试JavaBean / POJO的getter和setter方法对是否正确运行。

2.验证类的equals和hashCode方法是否分别符合Equals Contract和HashCode Contract。

3.验证对象相等中的属性重要性。“

我仍然有很多特定于meanbean的问题:它是否验证了equals()和hashCode()的一致性。另外,我没有努力打败它。我相信它不支持compareTo()。而我还没有尝试过替代方案。对其他人的经历感兴趣。