1

我对字典的 CollectionAssert.AreEqual 感到困惑。我已经写了以下测试。

    [Test]
    public void DictionaryAssertTest()
    {
        const int count = 2;

        IDictionary<string, string> dictionary = new Dictionary<string, string>();
        for (int i = 0; i < count; i++)
            dictionary.Add(i.ToString(), i.ToString());

        IDictionary<string, string> reversedictionary = new Dictionary<string, string>();
        for (int i = count -1; i >= 0 ; i--)
            reversedictionary.Add(i.ToString(), i.ToString());


        //NOTE: Expecting this to fail but does not
        CollectionAssert.AreEqual(dictionary, reversedictionary);

        //NOTE: When I first convert to List and then pass as parameter it fails 
        CollectionAssert.AreEqual(dictionary.ToList(), reversedictionary.ToList());
    }

我就是为什么这不会通过单元测试

        CollectionAssert.AreEqual(dictionary, reversedictionary);
4

1 回答 1

3

简单的答案:因为 IDictionary (您的第一个断言)中的元素顺序与 AreEqual 约束无关,但 IEnumerable (您的第二个断言)中的元素顺序是相关的。

细节:

当两个参数都是 IDictionaries 时,NUnit 使用 NUnitEqualityComparer.DictionariesEqual() 方法来比较您的字典。此方法检查这两个字典是否具有相同的键集(在您的情况下是这样,顺序无关紧要),然后检查每个键的对应值是否相等。

但是当您首先调用 .ToList() 时,NUnit 使用 NUnitEqualityComparer.EnumerablesEqual() 方法来比较您的配对列表。此方法检查两个列表中相同位置的元素是否相等,这在您的情况下不正确 - pair ("0"; "0") 不等于 pair ("1"; "1")

如果您希望在考虑元素顺序的情况下比较字典,该怎么办?两种方式:

1)像现在一样将它们都投射到列表中。

2) 实现 IComparer 接口并将其实例作为第三个参数传递给 AreEqual 断言:

CollectionAssert.AreEqual(dictionary, reversedictionary, myComparer);
于 2013-11-12T18:06:33.250 回答