单元测试:克隆和平等

时间:2015-08-11 09:55:42

标签: c# .net unit-testing

我正在编写单元测试并考虑实现IClonable的类型的场景。 所以当然我希望有一个测试Clone()方法的单元测试。

[Test]
public void CloneObject()
{
    MyType original = new MyType();
    MyType clone = (MyType)original.Clone();

    // Assert for equality
}

所以我的第一个任务就是让Assert获得平等。我看到以下选项:

  • 浏览MyType的所有属性(字段)并逐一检查
  • Equals()中覆盖MyType,让MyType说两个实例是否相等(考虑到有时候测试的相等性被视为生产代码的相等)
  • 如果实例相同,请检查某种序列化(对于该场景,MyType必须是[Serializable],但如果它具有例如接口属性,则有时很难做到)
  • ... ...

对于前两个我可以设置我的测试并且它们运行良好。但是如果我更改MyType并添加其他属性怎么办?如果Clone()没有复制这个并且我没有将它添加到checked属性列表或equals方法中,即使没有复制属性,我的测试仍会通过。

你如何解决这种测试?

2 个答案:

答案 0 :(得分:5)

您可以使用FluentAssertions库(TDD必备,IMO),其中ShouldBeEquivalent方法可以执行两个对象的graph comparison

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);

有用的链接:

答案 1 :(得分:0)

我赞成实施Equals()。我认为没有理由为什么Equals()需要在生产和测试中产生不同的结果。

如果你不这样做,你的Assert可以调用object.ReferenceEquals(),如下所示:

Assert.IsTrue(object.ReferenceEquals(expectedObject, objectInHand));