2011-06-13 242 views
10

我有一個從一個集合中獲取對象的方法的單元測試。這種情況一直存在,我看不出爲什麼,所以我在下面創建了一個非常簡單的測試來創建2個供應商對象,並測試它們是否相等,以查看我是否可以在我的代碼測試中發現問題。但是這個測試再次失敗。任何人都能看到或解釋爲什麼?單元測試Assert.AreEqual失敗

[TestMethod()] 
    public void GetSupplierTest2() 
    { 
     Supplier expected = new Supplier(); 
     expected.SupplierID = 32532; 
     expected.SupplierName = "Test 1" 

     Supplier actual = new Supplier(); 
     actual.SupplierID = 32532; 
     actual.SupplierName = "Test 1" 

     Assert.AreEqual(expected, actual); 
    } 

但如果我測試測試通過對象的個別屬性...

[TestMethod()] 
    public void GetSupplierTest2() 
    { 
     Supplier expected = new Supplier(); 
     expected.SupplierID = 32532; 
     expected.SupplierName = "Test 1" 

    Supplier actual = new Supplier(); 
     actual.SupplierID = 32532; 
     actual.SupplierName = "Test 1" 

     Assert.AreEqual(expected.SupplierID , actual.SupplierID); 
     Assert.AreEqual(expected.SupplierName , actual.SupplierName); 
    } 

回答

4

如果要比較供應商的兩個不同實例,並且希望在某些屬性具有相同值時將它們視爲相等,則必須覆蓋Supplier上的Equals方法並比較方法中的這些屬性。

你可以閱讀更多有關Equals方法在這裏:http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

實現示例:

public override bool Equals(object obj) 
{ 
    if (obj is Supplier) 
    { 
     Supplier other = (Supplier) obj; 
     return Equals(other.SupplierID, this.SupplierID) && Equals(other.SupplierName, this.SupplierName); 
    } 
    return false; 
} 

需要注意的是,你還可以得到,你必須執行的GetHashCode以及編譯器警告,這可能就像這樣簡單:

public override int GetHashCode() 
{ 
    return SupplierID; 
} 
+0

您是否可以擴展Equals方法? – suggy1982 2011-06-13 08:48:38

2

你比較供應商類型的2個不同的實例,這就是爲什麼斷言失敗。

如果要供應商是平等的說,(通過編號)可以覆蓋的Equals方法,這裏非常超過simpled例如:d。

public class Supplier 
{ 
    private int id; 
    private string name; 

    public int Id 
    { 
     get { return id; } 
    } 

    public string Name 
    { 
     get { return name; } 
    } 

    public bool Equals(Supplier other) 
    { 
     if(other == null) return false; 
     return other.id == id; 
    } 

    public override bool Equals(object obj) 
    { 
     if(obj == null) return false; 
     if (obj.GetType() != typeof (Supplier)) return false; 
     return Equals((Supplier) obj); 
    } 

    public override int GetHashCode() 
    { 
     return id; 
    } 
} 
+0

謝謝,那麼你將如何測試這樣的場景?僅僅比較每個屬性的值是否是正確的方法,或者是否存在將對象與對象進行比較的方法? – suggy1982 2011-06-13 08:44:48

+0

你可以覆蓋Equals功能 – 2011-06-13 08:46:27

+0

你可以擴展一點嗎? – suggy1982 2011-06-13 08:48:14

1

測試各個屬性時,比較字符串/整數值。他們是平等的,所以測試通過。

測試父對象時,只比較兩個類型爲Supplier的容器結構 - 即使這些容器結構可能具有相同的屬性值,但它們並不相等:由於您正在實例化兩個單獨的對象,因此它們不駐留在內存中的地址相同。

+0

謝謝,那麼你將如何測試這樣的場景?有沒有比較對象與對象的方法? – suggy1982 2011-06-13 08:45:41

+0

正如其他兩張海報所建議的那樣,您可以覆蓋供應商類型的Equals方法並讓它比較各個屬性值。請參閱本教程,例如:http://msdn.microsoft.com/en-us/library/336aedhh(v=vs.71).aspx – weltraumpirat 2011-06-13 08:56:01

22

正如其他答案所說的問題是,你試圖比較的實例[可能]沒有重寫Equals方法。 但我不認爲你應該覆蓋Equals爲測試目的,因爲它可能會影響生產代碼或您可能需要在生產代碼中的其他Equals邏輯。

相反,您應該在第一個示例中(如果您沒有很多要比較整個對象的位置)或者將此比較邏輯封裝在某個類中,並且使用它類:

static class SupplierAllFieldsComparer 
{ 
    public static void AssertAreEqual(Supplier expected, Supplier actual) 
    { 
     Assert.AreEqual(expected.SupplierID , actual.SupplierID); 
     Assert.AreEqual(expected.SupplierName , actual.SupplierName);    
    } 
} 

//測試代碼:

SupplierAllFieldsComparer.AssertAreEqual(expected, actual); 
+2

我完全同意。我建議閱讀此:http://stackoverflow.com/questions/1180044/should-one-override-equals-method-for-asserting-the-object-equality-in-a-unit-tes – steenhulthin 2011-06-13 09:03:45

3

Object.Equals引用類型的默認實現爲「參考平等」(即類別):是兩個物體實際上相同實例。它不會比較字段的值。

或者(如其他人所示)替代Equals以給出「價值平等」。在這種情況下,您還必須覆蓋GetHashCode(因此容器工作),並且應該覆蓋operator ==

或者接受大多數實體應該有引用平等(兩個同名的供應商並不總是相同的組織),並直接實際使用這些屬性。

0
//Given the following structure and an instance value, targetObj... 

class BaseType 
{ 
    private FeatureType Feature_1; 
} 

class TargetType : BaseType 
{ 
    ... 
} 

TargetType targetObj = new TargetType(); 

//...a private feature in a specific base class can be accessed as follows 

PrivateType typeCast = new PrivateType(typeof(BaseType)); 

PrivateObject privateObj = new PrivateObject(targetObj, typeCast); 

//...and values can be retrieved and set as follows.... 

privateObj.SetField("Feature_1", (FeatureType) newValue); 

FeatureType result = (FeatureType) privateObj.GetField("Feature_1"); 

/* 對於圍繞在單元測試中訪問私有領域的爭論,我相信它應該永遠不會,除非絕對neccessary(即時間和費用管理問題)一起使用。 */