【问题标题】:Cannot compare lists in UnitTests无法比较单元测试中的列表
【发布时间】:2013-11-01 10:02:54
【问题描述】:

我需要在单元测试中比较如下列表:

var x = new List<object>() { new List<int>() };
var y = new List<object>() { new List<int>() };
CollectionAssert.AreEqual(x, y, "Expected response not the same as actual response.");

但我总是遇到以下异常,我该如何克服呢?

[Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException] = {“CollectionAssert.AreEqual 失败。预期的响应与 实际响应。(索引 0 处的元素不匹配。)"}

【问题讨论】:

标签: c# unit-testing


【解决方案1】:

根据 msdn 文档。 http://msdn.microsoft.com/en-us/library/ms243736.aspx

如果两个集合在同一个集合中具有相同的元素,则它们是相等的 订单和数量。如果它们的值相等,则元素相等,而不是 如果它们引用同一个对象。比较元素的值 默认使用 Equals。

现在看来集合是相等的。直到你深入了解。根据文档

以相同的顺序和数量拥有相同的元素

从您的示例中,它们没有相同的元素。它们具有相同类型的元素,并且这些元素具有相似的签名,但是这两个元素并不相同。它们是完全不同的对象。

使用“相同顺序的相同元素”运行您的测试,看看结果如何。比如。

List<int> list = new List<int>();
var x = new List<object>() { list };
var y = new List<object>() { list };
CollectionAssert.AreEqual(x, y, "Expected response not the same as actual response.");

你会发现这个参数列表满足CollectionAssert.AreEqual的参数。

希望这能解决问题。

【讨论】:

    【解决方案2】:

    这是因为

    new List<int>().Equals(new List<int>())
    

    返回False。外部列表不相等,因为内部列表不相等。

    您可以尝试使用接受ICompareroverload,它将您的两个空列表视为平等。

    【讨论】:

      【解决方案3】:

      作为替代方案,您可以考虑使用与 Microsoft 单元测试兼容的 FluentAssertions 单元测试框架。

      那么你的代码会变成:

      var x = new List<object>() { new List<int>() };
      var y = new List<object>() { new List<int>() };
      
      x.ShouldBeEquivalentTo(y, "Expected response not the same as actual response.");
      

      它也适用于这种事情:

      var ints1 = new List<int>();
      var ints2 = new List<int>();
      
      ints1.Add(1);
      ints2.Add(1);
      
      var x = new List<object>() { ints1 };
      var y = new List<object>() { ints2 };
      
      x.ShouldBeEquivalentTo(y, "Expected response not the same as actual response.");
      

      如果您将ints2.Add(1); 更改为ints2.Add(2);,则单元测试将正确失败。

      请注意,ShouldBeEquivalentTo() 递归地递减被比较的对象并处理集合,因此即使是列表列表也可以使用它 - 例如:

      var ints1 = new List<int>();
      var ints2 = new List<int>();
      
      ints1.Add(1);
      ints2.Add(1); // Change this to .Add(2) and the unit test fails.
      
      var objList1 = new List<object> { ints1 };
      var objList2 = new List<object> { ints2 };
      
      var x = new List<object> { objList1 };
      var y = new List<object> { objList2 };
      
      x.ShouldBeEquivalentTo(y, "Expected response not the same as actual response.");
      

      【讨论】:

        【解决方案4】:

        您应该使用 SelectMany 提取外部列表的内容,然后检查是否相等,例如:

        var x = new List<object>() { new List<int>() };
        var y = new List<object>() { new List<int>() };
        
        var xItems=x.SelectMany(item=>item);
        var yItems=y.SelectMany(item=>item);
        CollectionAssert.AreEqual(xItems, yItems, "Expected response not the same as actual response.");
        

        正如其他人所指出的,AreEqual 在每个项目上使用Equals 来检查是否相等,显然两个不同的 List 实例永远不会相等。

        【讨论】:

          【解决方案5】:

          您比较两个空列表的引用,如果您需要比较内部值类型,您必须手动比较它(例如编写 List 扩展名)。

          示例扩展。

          [TestClass]
          public class UnitTest1
          {
              [TestMethod]
              public void TestMethod1()
              {
                  var x = new List<object>() { new List<int>(){1} };
                  var y = new List<object>() { new List<int>(){1} };
                  x.SequenceRecursiveEqual(y);
          
              }
          }
          
          public static class ExtenderListAssert
          {
              public static void SequenceRecursiveEqual(this IList sourse, IList expected)
              {
                  if (sourse.Count != expected.Count)
                      Assert.Fail();
                  else
                  {
                      for (var i = 0; i < sourse.Count; i++)
                      {
                          var left = sourse[i];
                          var right = expected[i];
                          if(left is IList && right is IList)
                          {
                              (left as IList).SequenceRecursiveEqual(right as IList);
                          }
                          else
                          {
                              Assert.AreEqual(left, right);
                          }
                      }
                  }
              }
          }
          

          【讨论】:

            【解决方案6】:

            您可以使用SequenceEqual 并检查返回的布尔值是否有断言

            【讨论】:

            • 相信这是 NUnit 特有的。 OP 似乎正在使用 Visual Studio 测试工具。
            • 这些集合中的整数列表不相同,所以 SequenceEqual 将返回 false
            【解决方案7】:

            使用这种类型:

             [TestMethod]
             public void AreEqualTest1()
             {
               List<string> countries1 = new List<string> { "Israel", "USA", "Germany" };
               List<string> countries2 = new List<string> { "Israel", "USA", "Germany" };
               // First compare count of both collections:countries1 && countries2 =>
               // if not the same  count => test failed.
               // Otherwise copmare the equality items of  both collections in order, 
              // if one of the comparison  failed => test failed
               // otherwise =>=> test passed.
               CollectionAssert.AreEqual(countries1, countries2, "Not equal, hence failed");
             }
            

            【讨论】:

            • 这个答案与问题有什么关系?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-06-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多