一个单元应该如何测试hashCode-equals合约?

Pau*_*ley 72 java oop unit-testing

简而言之,hashCode契约,根据Java的object.hashCode():

  1. 除非影响equals()的内容发生变化,否则哈希码不应更改
  2. equals()表示哈希码是==

让我们主要关注不可变数据对象 - 它们的信息在构造之后永远不会改变,因此假定#1成立.留下#2:问题只是确认等于隐含代码==.

显然,我们无法测试每个可想到的数据对象,除非该集合很小.那么,编写可能会遇到常见情况的单元测试的最佳方法是什么?

由于此类的实例是不可变的,因此构造此类对象的方法有限; 如果可能的话,这个单元测试应该涵盖所有这些.在我的脑海中,入口点是构造函数,反序列化和子类的构造函数(应该可以简化为构造函数调用问题).

[我打算通过研究来回答我自己的问题.来自其他StackOverflowers的输入是这个过程的一个受欢迎的安全机制.]

[这可能适用于其他OO语言,所以我添加了该标签.]

Ben*_*ers 69

EqualsVerifier是一个相对较新的开源项目,它在测试equals合同方面做得非常好.它没有来自GSBase的EqualsTester 存在的问题.我肯定会推荐它.

  • 只是_using_ EqualsVerifier教我一些关于Java的东西! (7认同)
  • @JBRainsberger嗨!EqualsVerifier的创建者在这里.对不起,你发现它令人困惑.Re:不覆盖equals:您可以使用"allFieldsShouldBeUsed()"启用预期的行为.由于您声明的原因,这将是下一版本中的默认值.Re:相同的实例:如果没有看到一些示例代码,我认为我无法帮助您.您能否详细说明一个新问题,或者在https://groups.google.com/forum/?fromgroups#!forum/equalsverifier上的EV邮件列表中详细说明?谢谢! (7认同)

Eli*_*ght 11

我的建议是考虑为什么/如何不成立,然后写一些针对这些情况的单元测试.

例如,假设您有一个自定义Set类.如果两个集合包含相同的元素,则它们是相等的,但如果这些元素以不同的顺序存储,则两个相等集合的基础数据结构可能不同.例如:

MySet s1 = new MySet( new String[]{"Hello", "World"} );
MySet s2 = new MySet( new String[]{"World", "Hello"} );
assertEquals(s1, s2);
assertTrue( s1.hashCode()==s2.hashCode() );
Run Code Online (Sandbox Code Playgroud)

在这种情况下,集合中元素的顺序可能会影响它们的散列,具体取决于您实现的散列算法.所以这就是我要编写的那种测试,因为它测试的情况我知道一些哈希算法可能会为我定义的两个对象产生不同的结果.

您应该使用与您自己的自定义类相似的标准,无论它是什么.


小智 6

值得使用junit插件.查看类EqualsHashCodeTestCase http://junit-addons.sourceforge.net/你可以扩展这个并实现createInstance和createNotEqualInstance,这将检查equals和hashCode方法是否正确.