单元测试 - 当你的代码几乎只是一个计算(例如GetHashCode)时,你会怎么做?

m-y*_*m-y 4 c# unit-testing assert gethashcode

public class Foo
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Z { get; set; }

    public override int GetHashCode()
    {
        var hash = 17;
        hash *= 23 + x.GetHashCode();
        hash *= 23 + y.GetHashCode();
        hash *= 23 + z.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

当你去单元测试GetHashCode时,我在计算原始组件和重复函数或使用预定值之间徘徊:

[TestMethod]
public void Test1
{
    var x = 1; y = 2; z = 3;
    var foo = new Foo() { X = x, Y = y, Z = z };

    var hash = 17;
    hash *= 23 + x.GetHashCode();
    hash *= 23 + y.GetHashCode();
    hash *= 23 + z.GetHashCode();

    var expected = hash;
    var actual = foo.GetHashCode();

    Assert.AreEqual(expected, actual);
}

[TestMethod]
public void Test2
{
    var x = 1; y = 2; z = 3;
    var foo = new Foo() { X = x, Y = y, Z = z };

    var expected = ? //Some predetermined value (calculated by hand?)
    var actual = foo.GetHashCode();

    Assert.AreEqual(expected, actual);
}
Run Code Online (Sandbox Code Playgroud)

或者还有其他方式吗?

Dom*_*nic 5

单元测试用于测试逻辑.是GetHashCode计算本身的逻辑?不是真的,虽然意见可能会有所不同

这里的相关逻辑是两个相等的对象具有相同的哈希码,即Equals并且HashCode是兼容的.或者,引用文档:

  • 如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.

  • 为对象GetHashCode方法必须一致,只要没有修改确定的该对象的Equals方法返回值的对象的状态返回相同的散列码.请注意,这仅适用于当前应用程序的执行,并且如果再次运行应用程序,则可以返回不同的哈希代码.

所以我会编写单元测试来保证满足这些条件,而不是内部实现GetHashCode匹配预定的过程.

您的两个示例测试都非常脆弱,完全有效的GetHashCode实现会使它们失败.回想一下,单元测试的主要目的之一是允许重构而不用担心.但是,没有GetHashCode你的单元测试破坏,没有人可以重构.