我对字典的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);
答案 0 :(得分:3)
简单回答:因为IDictionary中的元素顺序(你的第一个断言)与AreEqual约束无关,但IEnumerable(你的第二个断言)中元素的顺序是相关的。
详细说明:
当两个参数都是IDictionaries时,NUnit使用NUnitEqualityComparer.DictionariesEqual()方法来比较您的词典。此方法检查这两个字典是否具有相同的键集(在您的情况下是正确的,顺序无关紧要),然后检查每个键对应的值是否相等。
但是当您首先调用.ToList()时,NUnit使用NUnitEqualityComparer.EnumerablesEqual()方法来比较您的对列表。此方法检查两个列表中相同位置的元素是否相等,在您的情况下不成对 - 对(“0”;“0”)不等于对(“1”;“1”)
如果您想要将字典与元素的顺序进行比较,可以做些什么?两种方式:
1)像现在一样将它们投射到列表中。
2)实现IComparer接口并将其实例作为第三个参数传递给AreEqual断言:
CollectionAssert.AreEqual(dictionary, reversedictionary, myComparer);