2012-09-26 80 views
10

我有一個類MyCustomClass:當我比較兩個空列表時,爲什麼測試'Assert.AreEqual'失敗?

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) 

試驗已經失敗了,爲什麼?每個屬性,靜態成員等都是一樣的。

回答

19

在這種情況下,Assert.AreEqual將檢查兩個對象是否相同,而他們不是。您應該使用CollectionAssert.AreEqual,如果兩個「具有相同順序和數量的相同元素」,則返回true。

+0

+1您是否在提問之前開始回答:)?注意:'AreEqual'覆蓋字符串實際比較值而不是「對象是相同的」。 –

+0

@AlexeiLevenkov'AreEqual'只是調用對象的'Equals'方法。 Equals的字符串實現比較值,List實現比較引用。每個班級都可以做任何想做的事情;這不像是對絃樂或類似的東西有特殊的支持。 – Servy

+0

@Servy,好點。我會避免使用「相同」的語句關於比較對象在C#/。淨 - 而是明確地說「相同的參考」/「相同通過運營商=」/「相同通過等於」...(順便說一句,我喜歡你刪除你的回答) –

4

作爲already answered,具有零元素的相同類型的兩個列表不被認爲是相等的。

背後的原因是,AreEqual實際上調用aux.AreEqual(oClass.MyObject),使用對象自己的等式實現。因爲List<T>沒有被覆蓋,所以回到Object的實現中,這是一個簡單的引用相等檢查。這兩個清單顯然不是同一個參考文獻,因此,它們並不相同。

因爲Equals方法存在並且是Object虛擬的,你自己的類可以以提供比參考平等機會的另一個概念覆蓋Equals。這是在像String這樣的對象上完成的,如果數據是相同的,那麼它們即使對於不同的引用也是相等的。

0

我反編譯Assert.AreEqual使用dotPeek(這是在Microsoft.VisualStudio.QualityTools.UnitTestFramework GAC組件),並發現,Assert.AreEqual(aux, oClass.MyObject)最終將導致下面的調用,其中auxexpectedoClass.MyObjectactual

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

documentation爲靜態object.Equals(Object, Object)我們閱讀:

靜態等於(對象,對象)方法指示兩個 對象objA和objB是否相等。它還使您能夠測試其值爲相等的值爲空的對象 。它比較objA和objB爲 的等式如下:

它確定兩個對象是否代表相同的對象 引用。如果他們這樣做,該方法返回true。該測試是 等同於調用ReferenceEquals方法。另外,如果 objA和objB都爲null,則該方法返回true。

它確定objA或objB是否爲空。如果是這樣,則返回 false。

如果兩個對象不表示相同的對象引用,並且 既不爲空,也會調用objA.Equals(objB)並返回結果。 這意味着如果objA重寫Object.Equals(Object)方法,則調用此重寫。現在

List<T>被稱爲是引用類型,而我們知道,不管你是在比較兩個列表是空的,所以你的兩個物體之間的最終比較會

expected.Equals(actual) 

由於List<T>不會覆蓋Equals,它使用執行參考比較的基礎對象實現,從而失敗(expectedactual分別爲「新建」)。

你想要的是結構比較,即列表中元素的成對相等。請參閱@ReedCopsey答案,以獲得正確的斷言(CollectionAssert.AreEqual)。

相關問題