简体   繁体   English

单元测试:克隆与平等

[英]Unit Test: Clone and equality

I am writing Unit Tests and thinking about the scenario of a type that implements IClonable . 我正在编写单元测试,并考虑实现IClonable的类型的场景。 So of course I want to have a Unit Test that tests the Clone() method. 因此,我当然希望有一个测试Clone()方法的单元测试。

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

    // Assert for equality
}

So my first task it to have an Assert for the equality. 因此,我的首要任务是为平等做一个Assert I see following options: 我看到以下选项:

  • going through all properties (fields) of MyType and check them one by one 浏览MyType所有属性(字段)并逐一检查
  • override Equals() in MyType to let MyType say if two instances are equal (consider that sometimes equality for tests is considered different of equality for production code) MyType重写Equals()以让MyType说两个实例是否相等(考虑到有时将测试的相等性视为生产代码的相等性不同)
  • Check with some kind of serialization if the instances are equal (for that scenario MyType would have to be [Serializable] , but that sometimes is hard to do if it has eg Interface Properties) 检查某种序列化的实例是否相等(对于这种情况, MyType必须为[Serializable] ,但是如果它具有例如Interface Properties,有时很难做到)
  • ...?? ... ??

For the first two I can setup my tests and they work well. 对于前两个,我可以设置测试,并且它们运行良好。 But what if I change MyType and add an additional property? 但是,如果我更改MyType并添加其他属性怎么办? If Clone() doesn't copy this and I don't add it in the list of checked properties or the equals method my test still passes even if the property does not get copied. 如果Clone()不复制此内容,并且我不将其添加到检查的属性或equals方法的列表中,即使该属性未复制,我的测试仍会通过。

How do you solve this kind of tests? 您如何解决这种测试?

You can use the FluentAssertions library (a TDD must-have, IMO), which has a ShouldBeEquivalent method that performs graph comparison of the two objects: 您可以使用FluentAssertions库(TDD必须具备的IMO),该库具有ShouldBeEquivalent方法,该方法执行两个对象的图形比较

original.ShouldBeEquivalentTo(clone);

The comparison algorithm can be customized via the optional options parameter; 可以通过可选的options参数自定义比较算法。 see their wiki for detailed info. 有关详细信息,请参见其Wiki

To make the test future-proof (ie, it breaks when new properties are added to the class, but not to the Clone method), you might want to test cloning an object with all its properties set to random non-default values. 为了使测试能够适应未来需求(即,在将新属性添加到类而不是 Clone方法时,它会中断),您可能想测试克隆对象的所有属性都设置为随机非默认值的情况。 AutoFixture can do that for you. AutoFixture可以为您做到这一点。

// Arrange
var fixture = new Fixture();
var original = fixture.Create<MyType>();

// Act
var clone = original.Clone();

// Assert
clone.ShouldBeEquivalentTo(original);

Useful links: 有用的链接:

I would favor implementing Equals(). 我更喜欢实现Equals()。 I see no reason why Equals() needs to produce different results in production vs. in tests. 我看不出Equals()在生产与测试中需要产生不同结果的原因。

If you don't do that, your Assert could call object.ReferenceEquals(), as follows: 如果不这样做,则您的Assert可以调用object.ReferenceEquals(),如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM