比较两个列表<;字符串[]>;C#单元测试中的对象

比较两个列表<;字符串[]>;C#单元测试中的对象,c#,arrays,list,unit-testing,equality,C#,Arrays,List,Unit Testing,Equality,我正在尝试创建一个单元测试来比较两个字符串数组列表 我尝试创建两个完全相同的列表对象,但是当我使用CollectionAssert.AreEqual时(预期,实际),测试失败: [TestMethod] public void TestList() { List<string[]> expected = new List<string[]> { new string[] { "John", "Smith", "200" }, new

我正在尝试创建一个单元测试来比较两个字符串数组列表

我尝试创建两个完全相同的
列表
对象,但是当我使用
CollectionAssert.AreEqual时(预期,实际),测试失败:

[TestMethod]
public void TestList()
{
    List<string[]> expected = new List<string[]> {
        new string[] { "John", "Smith", "200" },
        new string[] { "John", "Doe", "-100" }
    };

    List<string[]> actual = new List<string[]> {
        new string[] { "John", "Smith", "200" },
        new string[] { "John", "Doe", "-100" }
    };

    CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
公共void测试列表()
{
预期列表=新列表{
新字符串[]{“John”、“Smith”、“200”},
新字符串[]{“John”、“Doe”、“-100”}
};
实际列表=新列表{
新字符串[]{“John”、“Smith”、“200”},
新字符串[]{“John”、“Doe”、“-100”}
};
收款资产等于(预期、实际);
}
我还尝试了
Assert.IsTrue(expected.SequenceEqual(actual)),但这也失败了

如果我比较两个字符串列表或两个字符串数组,这两种方法都有效,但当比较两个字符串数组列表时,它们不起作用

我假设这些方法失败,因为它们比较的是两个对象引用列表,而不是数组字符串值


如何比较两个
列表
对象并判断它们是否真的相同?

CollectionAssert.AreEqual(预期、实际)失败,因为它比较对象引用<代码>预期的
实际的
指的是不同的对象

Assert.IsTrue(预期的.SequenceEqual(实际的))由于相同的原因失败。这次比较了
expected
actual
的内容,但元素本身是不同的数组引用

可能尝试使用以下方法展平两个序列:


正如Enigmativity在他的评论中正确地注意到的,SelectMany可能会在数组数量和/或其元素不同时给出积极的结果,但将列表展平将导致元素数量相等。只有在这些数组中始终具有相同数量的数组和元素的情况下才是安全的。

最好的解决方案是检查每个子集合中的项目以及每个子集合中的项目数量

试试这个:

bool equals = expected.Count == actual.Count &&
              Enumerable.Range(0, expected.Count).All(i => expected[i].Length == actual[i].Length &&
                                                           expected[i].SequenceEqual(actual[i]));
Assert.IsTrue(equals);
这将检查:

  • 两个列表的长度相同
  • 两个列表中的所有子集合对具有相同的长度
  • 每对子集合中的项目都是相同的

注意:使用
SelectMany
不是一个好主意,因为如果第二个列表中的项目相同,但分散在不同的子集合中,则可能会产生误报。我的意思是,它会考虑两个列表是相同的,即使第二个在同一个子集合中都有相同的项目。

它是失败的,因为列表中的条目是对象(<代码> String []/COD>)而且,由于您没有指定
CollectionAssert.AreEqual
应该如何比较两个序列中的元素,因此它返回到默认行为,即比较引用。例如,如果要将列表更改为以下内容,您会发现测试通过,因为现在两个列表都引用了相同的数组:

var first = new string[] { "John", "Smith", "200" };
var second = new string[] { "John", "Smith", "200" };

List<string[]> expected = new List<string[]> { first, second};
List<string[]> actual = new List<string[]> { first, second};

试试这个:
expected.Zip(实际的,(e,a)=>e.SequenceEqual(a)).All(x=>x)
。出于好奇。。。如果它们具有相同的元素,但顺序不同,你会认为这些列表是“相等的”吗?另外,值得注意的是,字符串数组是对象的可怕替代品。@David对于这个特定的测试,我可以选择一个要求元素顺序相同的解决方案,以及一个忽略顺序的解决方案。我同意对象通常比字符串数组好。此代码是更大图片的一部分,需要采用此格式。@JeppeStigNielsen-极好的点re
.Zip
未比较完整长度。
.Contains(false)
negative的效率不比
高(或低)。All(x=>x)
。两者都“使用”源,直到找到
false
的条目。第一个将每个元素与
false
进行比较,并使用
bool
的默认相等比较器。第二个调用委托
谓词
,该谓词包装lambda箭头
x=>x
中的静态IL方法,并检查返回值。因为运行时在任何一种情况下都会进行内联,所以我认为两者的速度都一样快(我没有测量)。同意@Enigmativity。通过对对象引用的解释,您已经解决了这个问题,但是
.SelectMany
方法会产生一大堆“误报”,并且不需要
。Select(y=>y)
谢谢您的评论。我错过了。我编辑了我的帖子。
var first = new string[] { "John", "Smith", "200" };
var second = new string[] { "John", "Smith", "200" };

List<string[]> expected = new List<string[]> { first, second};
List<string[]> actual = new List<string[]> { first, second};
CollectionAssert.AreEqual(expected, actual, StructuralComparisons.StructuralComparer);