一个单元应该如何测试哈希码等于契约?

2022-08-31 12:38:20

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

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

让我们假设主要对不可变数据对象感兴趣 - 它们的信息在构建后永远不会改变,所以#1被假定为成立。剩下#2:问题只是确认equals意味着哈希代码==的问题。

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

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

[我将尝试通过研究来回答我自己的问题。来自其他StackOverflowers的输入是此过程的一个受欢迎的安全机制。

[这可能适用于其他OO语言,所以我正在添加该标签。


答案 1

EqualsVerifier是一个相对较新的开源项目,它在测试平等合约方面做得很好。它没有GSBase的EqualsTester所具有的问题。我肯定会推荐它。


答案 2

我的建议是想想为什么/如何这可能不成立,然后编写一些针对这些情况的单元测试。

例如,假设您有一个自定义类。如果两个集合包含相同的元素,则它们相等,但如果两个相等集合的基础数据结构以不同的顺序存储,则这两个集合可能会有所不同。例如: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() );

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

您应该对自己的自定义类使用类似的标准,无论那是什么。