2017-06-29 142 views
2

學習如何使用NUnit編寫單元測試。如何使用NUnit單元測試比較複雜對象

努力比較兩個複雜的對象。

有一個答案,一個非常類似的問題在這裏Comparing Two objects using Assert.AreEqual()雖然它看起來像你預期凌駕於你的對象Equals() - 這是不理想給了我多少的對象有可能是,你想比較,更不用說對象及其嵌套對象上可能存在的屬性的數量。

給出的樣本對象:

public class AMockObject 
    { 
     public int Id { get; set; } 
     public ICollection<int> Numbers { get; set; } 

     public AMockObject() 
     { 
      Numbers = new List<int>(); 
     }   
    } 

我想比較,這個對象的兩個單獨的實例具有相同的價值觀和我發現Assert.AreEqual()是不是真的做什麼我的預期。

例如,所有的這些失敗:

// Example 1 
AMockObject a = new AMockObject(); 
AMockObject b = new AMockObject(); 
Assert.AreEqual(a,b); // Fails - they're not equal 

// Example 2 
AMockObject a = new AMockObject() { Id = 1 }; 
AMockObject b = new AMockObject() { Id = 1 }; 
Assert.AreEqual(a, b); // Also fails 

// Example 3 
AMockObject a = new AMockObject() { Id = 1 }; 
a.Numbers.Add(1); 
a.Numbers.Add(2); 
a.Numbers.Add(3);  
AMockObject b = new AMockObject() { Id = 1 }; 
b.Numbers.Add(1); 
b.Numbers.Add(2); 
b.Numbers.Add(3);  
Assert.AreEqual(a, b); // also fails 

我們已制訂了代碼中我們克隆的各種對象,其中一些非常大的。 鑑於這是一件很常見的事情,有兩種測試方法可以測試兩個對象在屬性值級別是否相同?

這裏的例子有兩個屬性。在現實世界中,我有一個有幾十個屬性的對象,其中一些屬性是其他複雜對象的列表。

目前,我序列化對象和比較字符串,雖然這感覺不太理想。

+0

我認爲你的序列化方法可能不是那麼糟糕。否則,你會考慮重寫平等的東西,或者寫一些深刻的複雜的反思。 – Derek

+0

您需要考慮的名單,是1,2,3是否與3,1,2相同?訂貨是否重要?Xml比較可能最終會有所不同。 – Derek

+0

@Derek - 例如,訂單可能無關緊要。雖然只是做一個真正的比較而已。在我的現實世界中,情況並非如此,但這並不是說它不會。 – Darren

回答

2

在單元測試中有一個工具叫做Fluent Assertions,它可以進行這樣的比較。

注然而當兩個對象圖都同樣命名的那些無關 對象的類型的屬性 具有相同值,

對象是等價的。如果一個類型可以轉換爲 另一個類型並且結果相等,則兩個屬性也相等。只要集合實現了 System.Collections.IEnumerable並且集合中的所有項目在結構上相等,則 都將被忽略。請注意,實際行爲取決於由FluentAssertions.AssertionOptions管理的全局默認值 。

using FluentAssertions; 

//... 

// Example 1 
AMockObject a = new AMockObject(); 
AMockObject b = new AMockObject(); 
a.ShouldBeEquivalentTo(b); // Asserts that an object is equivalent to another object. 

// Example 2 
AMockObject a = new AMockObject() { Id = 1 }; 
AMockObject b = new AMockObject() { Id = 1 }; 
a.ShouldBeEquivalentTo(b); //Asserts that an object is equivalent to another object. 

// Example 3 
AMockObject a = new AMockObject() { Id = 1 }; 
a.Numbers.Add(1); 
a.Numbers.Add(2); 
a.Numbers.Add(3);  
AMockObject b = new AMockObject() { Id = 1 }; 
b.Numbers.Add(1); 
b.Numbers.Add(2); 
b.Numbers.Add(3); 
a.ShouldBeEquivalentTo(b)  
a.Numbers.ShouldAllBeEquivalentTo(b.Numbers); // Asserts that a collection of objects is equivalent to another collection of objects. 

Documentation here

+0

這看起來超級有趣!謝謝:) - 我沒有深入到他們的github,但不知道他們是否序列化對象,因爲類型被忽略(在我的情況不是問題) – Darren

+0

再次感謝你NKosi。我們也在踢BDD風格的測試用例,所以這個插槽很好。 – Darren

0

由於沒有別的改變,你可以簡單地比較創建的對象的屬性值?

+0

該示例有2個屬性。在現實生活中,我想比較的對象具有超過20個屬性,包括包含具有許多屬性的其他對象的列表 - 請考慮圖形。 – Darren

+0

在我的謙虛經驗中,我是這樣做的(不管對象屬性的數量和複雜度如何,無需修改equals和gethashvalue)。你可以斷言它們是同一類的實例(如果在你的場景中有意義),然後根據預定義的預期答案手動檢查這些值。 – marto

0

你可以使用反射(見get fields with reflection),並通過在這兩個類中的字段進行迭代。 FieldInfo.GetValue()應該爲您提供要比較的值。

+0

我假設你使用了反射?有很多代碼可以編寫,導致錯誤代碼的機會增加。我寧願不必寫一個單元測試來測試我的單元測試:) – Darren

+0

我同意這不是直截了當的,但它是一種製作一個比較規則全部模板的方法。看起來你正在尋找不那麼通用,所以這可能是一種矯枉過正。 –

+0

完整的完美比較是我理想中最喜歡和最終需要的。令人驚訝的是,這些領先的測試框架並沒有內置任何東西。 – Darren

相關問題