单元测试:克隆和相等
本文关键字:单元测试 | 更新日期: 2023-09-27 18:07:14
我正在编写单元测试,并考虑实现IClonable
的类型的场景。当然,我想要一个测试Clone()
方法的单元测试。
[Test]
public void CloneObject()
{
MyType original = new MyType();
MyType clone = (MyType)original.Clone();
// Assert for equality
}
所以我的第一个任务是得到等式的Assert
。我看到以下选项:
- 遍历
MyType
的所有属性(字段)并逐一检查 - 重写
MyType
中的Equals()
,让MyType
表示两个实例是否相等(考虑到有时测试代码的相等性被认为与生产代码的相等性不同) - 如果实例相等,检查某种序列化(在这种情况下,
MyType
必须是[Serializable]
,但有时很难做到,如果它有接口属性) - …? ?
对于前两个,我可以设置我的测试,它们工作得很好。但是如果我改变MyType
并添加一个额外的属性呢?如果Clone()
不复制这个,我没有将它添加到检查属性或equals方法的列表中,即使属性没有被复制,我的测试仍然通过。
你如何解决这类测试?
你可以使用FluentAssertions库(一个TDD必须有,IMO),它有一个ShouldBeEquivalent
方法,执行两个对象的图形比较:
original.ShouldBeEquivalentTo(clone);
比较算法可通过可选的options
参数自定义;查看他们的wiki获取详细信息。
为了使测试能够适应未来(即,当新属性被添加到类中,但不是添加到Clone
方法时,它会中断),您可能想要测试克隆一个对象,并将其所有属性设置为随机的非默认值。AutoFixture可以为你做这些。
// Arrange
var fixture = new Fixture();
var original = fixture.Create<MyType>();
// Act
var clone = original.Clone();
// Assert
clone.ShouldBeEquivalentTo(original);
的有用链接:
- FluentAssertions小抄
- AutoFixture备忘单(它有点过时,但它展示了它的大多数基本功能)
我倾向于实现Equals()。我看不出为什么Equals()需要在生产和测试中产生不同的结果。
如果你不这样做,你的Assert可以调用object.ReferenceEquals(),如下所示:
Assert.IsTrue(object.ReferenceEquals(expectedObject, objectInHand));