20

我很清楚合同需要确保与 .hashCode一致equals并且equalscompareTo. 然而,这在实践中经常被违反。是否有任何工具、技术或库可以自动测试这种一致性?

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

如果不清楚我所说的一致性是什么意思,hashCodeequals指的是以下内容:

如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。

对于equalscompareTo我指的是以下内容:

当且仅当 e1.compareTo(e2) == 0 对于 C 类的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,C 类的自然排序被称为与 equals 一致。

4

5 回答 5

12

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

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

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

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

于 2012-03-08T20:12:47.407 回答
5

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

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

于 2013-02-12T18:19:44.960 回答
1

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

“平均豆:

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

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

3. 验证对象相等的属性意义。

我还有很多关于meanbean 的问题:它是否验证equals() 和hashCode() 的一致性。再加上我没有努力打败它。我相信它不支持 compareTo()。而且我还没有尝试过替代品。对别人的经历感兴趣。

于 2012-11-09T16:23:34.943 回答
1

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

希望这可以帮助!

于 2012-03-08T20:35:25.760 回答
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>
于 2012-03-08T20:15:23.240 回答