当我比较两个空列表时,为什么测试'Assert.AreEqual'失败了?

时间:2012-09-26 16:24:25

标签: c# unit-testing

我有一个类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)

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

3 个答案:

答案 0 :(得分:19)

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

答案 1 :(得分:4)

作为already answered,两个具有零元素的相同类型的列表不被视为相等。

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

因为Equals方法存在且在Object上是虚拟的,所以您自己的类可以覆盖Equals,以便为参数相等提供另一个相等的概念。这是在像String这样的对象上完成的,如果数据相同,它们即使对于不同的引用也是相等的。

答案 2 :(得分:0)

我使用dotPeek反编译Assert.AreEqual(在Microsoft.VisualStudio.QualityTools.UnitTestFramework GAC汇编中),发现Assert.AreEqual(aux, oClass.MyObject)最终会导致以下调用auxexpectedoClass.MyObjectactual

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

documentation我们读到的静态object.Equals(Object, Object)

  

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

     

确定两个对象是否代表同一个对象   参考。如果是,则该方法返回true。这个测试是   相当于调用ReferenceEquals方法。另外,如果两者兼而有之   objA和objB为null,该方法返回true。

     

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

     

如果两个对象不表示相同的对象引用和   既不是null,它调用objA.Equals(objB)并返回结果。   这意味着如果objA重写Object.Equals(Object)方法,   调用此覆盖。

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

expected.Equals(actual)

由于List<T>未覆盖Equals,因此它使用执行引用比较的基础对象实现,因此失败(expectedactual为&#34;新的&#34;分开)。

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