10

我有一个类 MyCustomClass:

public MyCustomClass
{
    public MyCustomClass()
    {
        MyObject = new List<MyCustomObject>();
    }

    public List<MyCustomObject> MyObject {get; set;}
}

在测试中:

List<MyCustomObject> aux = new List<MyCustomObject>();
MyCustomClass oClass = new MyCustomClass();
Assert.AreEqual(aux, oClass.MyObject)

测试失败了,为什么?每个属性、静态成员等都是相同的。

4

3 回答 3

19

在这种情况下Assert.AreEqual,将检查两个对象是否相同,而它们不是。您应该CollectionAssert.AreEqual改用,如果两者“具有相同顺序和数量的相同元素”,它将返回 true。

于 2012-09-26T16:26:25.397 回答
4

正如已经回答的那样,具有零元素的两个相同类型的列表不被认为是相等的。

这背后的原因是,AreEqual实际上调用aux.AreEqual(oClass.MyObject),使用对象自己的相等实现。因为这没有被 覆盖List<T>,所以它回退到 中的实现Object,这是一个简单的引用相等检查。这两个列表显然不是同一个参考,因此,它们不被认为是平等的。

因为该Equals方法存在并且是 virtual on Object,所以您自己的类可以重写Equals,以便为相等性提供另一个概念,而不是引用相等性。这是在对象上完成的String,如果数据相同,即使对于不同的引用,这些对象也比较相等。

于 2012-09-26T16:32:04.253 回答
0

我使用dotPeekAssert.AreEqual反编译(在Microsoft.VisualStudio.QualityTools.UnitTestFramework GAC 程序集中),发现最终会导致以下调用 where is和is :Assert.AreEqual(aux, oClass.MyObject)auxexpectedoClass.MyObjectactual

object.Equals((object) expected, (object) actual)

从我们阅读的静态文档中:object.Equals(Object, Object)

静态 Equals(Object, Object) 方法指示两个对象 objA 和 objB 是否相等。它还使您能够测试值为 null 的对象是否相等。它比较 objA 和 objB 是否相等,如下所示:

它确定两个对象是否代表相同的对象引用。如果是,则该方法返回 true。此测试等效于调用 ReferenceEquals 方法。此外,如果 objA 和 objB 都为 null,则该方法返回 true。

它确定 objA 或 objB 是否为空。如果是,则返回 false。

如果这两个对象不代表同一个对象引用且都不为 null,则调用 objA.Equals(objB) 并返回结果。这意味着如果 objA 覆盖 Object.Equals(Object) 方法,则调用此覆盖。

现在,List<T>已知是引用类型,并且我们知道您要比较的两个列表都不是 null,因此您的两个对象之间的最终比较将是

expected.Equals(actual)

由于List<T>不覆盖Equals,它使用执行引用比较的基础对象实现,因此失败(expected并且actual分别“新”)。

您想要的是结构比较,即列表中元素的成对相等。CollectionAssert.AreEqual有关该 ( )的正确断言,请参阅@ReedCopsey 答案。

于 2012-09-26T16:50:29.723 回答