无法在单元测试中比较列表

4

我需要在我的单元测试中比较以下类似的列表:

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的元素不匹配)"}


类似的问题在这里:https://dev59.com/p2435IYBdhLWcg3w0Tnc - pazcal
7个回答

3
根据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。外部列表不相等,因为内部列表不相等。

您可以尝试使用接受 IComparer重载,将您的两个空列表视为相等。


1
作为替代方案,您可以考虑使用与Microsoft Unit Test兼容的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.");

0

你要比较两个空列表的引用,如果你需要比较内部值类型,你必须手动比较它(例如编写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);
                }
            }
        }
    }
}

0
你应该使用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实例永远不会相等。


-1

请使用此类型:

 [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");
 }

2
这个回答与问题有什么关联? - Sergey Berezovskiy

-1
你可以使用 SequenceEqual 并检查返回的布尔值进行断言。

相信这是特定于NUnit的。OP似乎正在使用Visual Studio测试工具。 - User 12345678
这些集合中的整数列表不同,因此SequenceEqual将返回false。 - Sergey Berezovskiy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接