如何使用NUnit单元测试比较复杂对象

时间:2017-06-29 12:43:20

标签: c# unit-testing 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

我们有代码,我们正在克隆各种对象,其中一些非常大。 鉴于这是一个非常常见的事情,是否有一种同样常见的方法来测试两个对象在属性值级别是否相同?

此处的示例有两个属性。在现实世界中,我有一个带有几十个属性的对象,其中一些是其他复杂对象的列表。

目前,我正在序列化对象并比较字符串,虽然这感觉不太理想。

4 个答案:

答案 0 :(得分:3)

单元测试中使用了一个名为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

答案 1 :(得分:1)

将其序列化为Json并进行比较

使用Newtonsoft.Json.JsonConverter,就可以做到。

var expected = JsonConvert.SerializeObject(a);
var result = JsonConvert.SerializeObject(b);

Assert.AreEqual(expected, result);

答案 2 :(得分:0)

由于没有其他任何变化,您只需比较所创建对象的属性值吗?

答案 3 :(得分:0)

您可以使用反射(请参阅get fields with reflection)并遍历两个类中的字段。 FieldInfo.GetValue()应该为您提供要比较的值。