2011-06-13 245 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(即时间和费用管理问题)一起使用。 */