在UNit测试中比较两个ArrayLists

时间:2017-07-31 12:01:20

标签: c# unit-testing arraylist

我写了一个单元测试,我要比较两个ArrayLists。 我确信这两个列表是相同的,测试应该通过,但他没有。

我将它们比作如下:

CollectionAssert.AreEqual(expected, actual)

expectedactual是这两个ArrayLists

我可以比较上面写的两个ArrayLists吗?

1 个答案:

答案 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());,断言将失败。