单元测试 - 当您的代码几乎只是一个计算(例如 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();
}
}
当您对 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);
}
或者还有其他方法吗?
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();
}
}
When you go to Unit Test the GetHashCode, I'm torn between calculating the original components and repeating the function or using a predetermined value:
[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);
}
Or is there some other way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
单元测试是为了测试逻辑。
GetHashCode
计算本身符合逻辑吗?事实并非如此,尽管意见可能有所不同。这里的相关逻辑是两个相等的对象具有相同的哈希码,即
Equals
和HashCode
是兼容的。或者,引用文档:因此,我会编写单元测试来保证满足这些条件,而不是
GetHashCode
的内部实现与预定过程匹配。您的两个示例测试都非常脆弱,并且完全有效的 GetHashCode 实现将使它们失败。回想一下,单元测试的主要目的之一是让重构无所畏惧。但是,没有人可以在不破坏单元测试的情况下重构
GetHashCode
。Unit testing is for testing logic. Is the
GetHashCode
calculation itself logic? Not really, although opinions may vary.The relevant logic here is that two objects that are equal have the same hash code, i.e.
Equals
andHashCode
are compatible. Or, quoting from the docs:So I would write unit tests that guarantee that those conditions are met, not that the internal implementation of
GetHashCode
matches a predetermined procedure.Both of your example tests are highly brittle, and perfectly valid
GetHashCode
implementations would fail them. Recall that one of the major purposes of unit tests is to allow refactoring without fear. But, nobody can refactorGetHashCode
without your unit tests breaking.我将结果与预先计算的值进行比较,并添加大量注释来解释为什么我选择正在测试的值。
对于纯粹的计算,我倾向于编写单元测试,以便确保函数保持使用它的代码所需/期望的条件。
示例条件:
I compare the result against pre-computed values with lots of commenting to explain why I chose the values being tested.
For pure calculations, I tend to write unit tests so that they ensure the function keeps the conditions that are required/expected of the code that will use it.
Example conditions: