2012-05-24 77 views
14

我有一個PagedModel類,它實現IEnumerable只返回ModelData,忽略分頁數據。我還重寫了Equals和GetHashCode,以允許通過它們的ModelData,PageNumber和TotalPages以及PageSize來比較兩個PagedModel對象。Assert.AreEqual不會在IEnumerable實現中使用我的.Equals覆蓋

這裏的問題

Dim p1 As New PagedModel() With { 
    .PageNumber = 1, 
    .PageSize = 10, 
    .TotalPages = 10, 
    .ModelData = GetModelData() 
} 

Dim p2 As New PagedModel() With { 
    .PageNumber = 1, 
    .PageSize = 10, 
    .TotalPages = 10, 
    .ModelData = GetModelData() 
} 

p1.Equals(p2) =====> True 
Assert.AreEqual(p1, p2) ======> False! 

它看起來像NUnit的是調用它的內部EnumerableEqual方法比較我PagedModel的,而不是使用equals我提供的方法!有什麼方法可以覆蓋這種行爲,或者我必須編寫自定義斷言。

回答

9

做你在問什麼:我會建議反對它,但如果你真的不喜歡NUnit的行爲,並想定製斷言,你可以提供自己的EqualityComparer。

Assert.That(p1, Is.EqualTo(p2).Using(myCustomEqualityComparer)); 

你應該做的事情(簡答):你需要的GetHashCode因爲你正在使用PagedModel作爲收集和ModelData的元素上ModelData而不是PagedModel等於。

你應該做的事情(龍答案): 而不是對PagedModel覆蓋Equals(object)你需要實現ModelData,其中T是類型參數了IEnumerable,以及覆蓋​​IEquatable<T>。這兩種方法是.Net中的所有IEnumerable方法在使用Default Equality Comparer(您沒有指定自己的IEqualityComparer)時用於確定相等性(對於諸如Union,Distinct等操作)。

[默認相等比較器]檢查類型T是否實現System.IEquatable接口,如果是,則返回使用該實現的EqualityComparer。否則,它返回使用由T.


提供的Object.Equals和Object.GetHashCode的覆蓋要正常運行的EqualityComparer,GetHashCode的需要返回相同的結果,對於.Equals返回true的所有對象(T)。反過來並不一定是真的 - GetHashCode可以返回不相等的對象的衝突。 More information here - see Marc Gravel's accepted answer。我也發現GetHashCode在使用素數非常有用的答案中的實現。

+0

這個答案的意思是說,本質上在你的實現中,你需要明確地實現IEquatable .Equals ...參見http://stackoverflow.com/questions/1577149/explicit-interface-implementation-in-vb-net – Jay

+0

不,實施IEquatable 是不夠的。 GetHashCode實現同樣重要。如果你沒有實現IEquatable (請參閱我的文章中的引用),那麼瞭解IEnumerable會回落到使用Equals(object),這一點也很重要,所以這不是絕對必需的。 – csauve

+0

我說明確實現IEquatable.Equals不應該允許默認回退,因爲該方法將覆蓋,並顯式實現將調用該方法... – Jay

1

如果你看一看在GIT repo NUnit的相等比較器的實現,你會看到有一個專門的比較塊的兩個枚舉,它具有更高的優先級(僅僅是因爲它被放在更高)比comparisons使用IEquatable<T>接口或Object.Equals(Object)方法,您已在PagedModel類中實施或重載。

我不知道這是否是一個錯誤或功能,但你應該問自己第一,如果直接通過您的PagedModel類實現IEnumerable<ModelData>接口實際上是最好的選擇,特別是因爲你的PagedModel的東西多隻是一個枚舉ModelData實例。

可能通過PagedModel類的簡單隻讀IEnumerable<ModelData>屬性來提供ModelData枚舉已經足夠(甚至更好)。 NUnit將停止查看您的PagedModel對象,因爲對象的簡單枚舉爲ModelData,並且您的單元測試將按預期行事。

唯一的其他選擇是由csauve建議的選項;實現一個簡單的自定義IComparer爲您PagedModel,並提供它的一個實例的所有斷言在那裏你會比較兩個PagedModel實例:

internal class PagedModelComparer : System.Collections.IComparer 
{ 
    public static readonly IComparer Instance = new PagedModelComparer(); 

    private PagedModelComparer() 
    { 
    } 

    public int Compare(object x, object y) 
    { 
     return x is PagedModel && ((PagedModel)x).Equals(y); 
    } 
} 

    ... 
    [Test] 
    ... 
     Assert.That(actual, Is.EqualTo(expected).Using(PagedModelComparer.Instance)); 
    ... 

但是,這將使你的測試超過必要的複雜,你將永遠有當您爲PagedModel編寫附加測試時,請考慮使用您的特殊比較器。

相關問題