我写了一个单元测试,我要比较两个ArrayLists
。
我确信这两个列表是相同的,测试应该通过,但他没有。
我将它们比作如下:
CollectionAssert.AreEqual(expected, actual)
expected
和actual
是这两个ArrayLists
。
我可以比较上面写的两个ArrayLists
吗?
答案 0 :(得分:5)
此处的问题是CollectionAssert.AreEqual()
将使用Equals()
比较元素。
对于不覆盖Equals()
的参考类型,将进行参考比较。这不是你想要的。
幸运的是,你可以解决这个问题,因为CollectionAssert.AreEqual()
has an overload that lets you specify a comparer。
因此,您需要做的就是创建一个比较器,如果两个元素相等则返回零,如果不相等则返回非零。由于ArrayList
存储对象这一事实,这有点复杂,因此您需要转换为正确的类型以进行比较。
(请注意,这有点滥用
IComparer
,因为它是 应该返回-ve,0或+ ve来提供有序的比较 左右两侧。但是,CollectionAssert.AreEqual()
只用它来测试相等性,所以它足以让我们返回 在我们的实施中为零或非零。理想情况下,
AreEqual()
方法会使用IEqualityComparer<T>
比较元素,但我认为后期AreEqual()
就这样了 在AreEqual()
被写入时不可用。)
假设您的元素属于string[]
类型(您说它们是),那么您可以创建一个比较器来比较元素,如下所示:
var comparer = Comparer<object>.Create((a, b) => ((string[]) a).SequenceEqual((string[]) b) ? 0 : 1);
然后您可以将该比较器传递给AreEqual()
。
一个例子可以说清楚:
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
list1.Add(Enumerable.Range( 0, 10).Select(n => n.ToString()).ToArray());
list1.Add(Enumerable.Range(10, 10).Select(n => n.ToString()).ToArray());
list1.Add(Enumerable.Range(20, 10).Select(n => n.ToString()).ToArray());
list2.Add(Enumerable.Range( 0, 10).Select(n => n.ToString()).ToArray());
list2.Add(Enumerable.Range(10, 10).Select(n => n.ToString()).ToArray());
list2.Add(Enumerable.Range(20, 10).Select(n => n.ToString()).ToArray());
var comparer = Comparer<object>.Create((a, b) => ((string[]) a).SequenceEqual((string[]) b) ? 0 : 1);
CollectionAssert.AreEqual(list1, list2, comparer);
此断言将成功,但要证明这将检测差异,请将最后list2.Add()
更改为list2.Add(Enumerable.Range(20, 9).Select(n => n.ToString()).ToArray());
,断言将失败。