首页 > 解决方案 > 如何将嵌套在字典中的集合与 NUnit 进行比较?

问题描述

正如这个答案所说,在较新版本的 NUnit 中,显然可以比较嵌套集合。但是,这似乎不适用于嵌套HashSet的 s。考虑:

var a1 = new Dictionary<string, HashSet<string>> { 
    { "a", new() { "b", "c" } },
    { "b", new() { "c" } },
    { "c", new() { } },
};
var a2 = new Dictionary<string, HashSet<string>> { 
    { "c", new() { } },
    { "a", new() { "b", "c" } },
    { "b", new() { "c" } },
};
CollectionAssert.AreEqual(a1, a2);

这通过了,但是如果我稍微更改向集合添加值的顺序(或做任何改变其中一个集合的迭代顺序的事情):

var a1 = new Dictionary<string, HashSet<string>> { 
    { "a", new() { "b", "c" } },
    { "b", new() { "c" } },
    { "c", new() { } },
};
var a2 = new Dictionary<string, HashSet<string>> { 
    { "c", new() { } },
    { "a", new() { "c", "b" } },
    { "b", new() { "c" } },
};
CollectionAssert.AreEqual(a1, a2);

我希望它仍然可以通过,因为 aHashSet是无序的,但是测试失败了:

  ----> NUnit.Framework.AssertionException :   Expected and actual are both <System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.HashSet`1[System.String]]> with 3 elements
  Values differ at index [0]
  String lengths are both 1. Strings differ at index 0.
  Expected: "b"
  But was:  "c"
  -----------^

似乎 NUnit 不知道那HashSet是无序的,但知道 aDictionary无序的。

所以我想我需要在HashSet<string>.CreateSetComparer()某个地方使用。我知道我可以指定用于比较的相等比较器Using

Assert.That(a, Is.EqualTo(b).Using(someEqualityComparer));

但我试图提供它来比较嵌套集。我该怎么做?

为了避免成为 XY 问题:我的真实代码中的字典实际上代表了控制流图的边缘。它实际上是一个Dictionary<BasicBlock, HashSet<BasicBlock>>.

标签: c#nunithashset

解决方案


NUnit 并不完全“意识到”字典是无序的。但是,它确实具有用于测试字典相等性的特殊代码,如本页所述。您会注意到该页面没有说明任何关于 Hashsets 的内容,它没有得到特殊处理。

正如您所建议的,在您的示例中处理 Hashset 的最简单方法是定义您自己的比较器。我建议定义一个,它实现,IEqualityComparer<Hashset>. 这将自动解决嵌套问题,因为 NUnit 只会在到达嵌套的 Hashset 时使用该比较器。

如有必要,您可以重复Using为不同类型创建多个比较器。但是,从您所说的情况来看,在这种情况下似乎没有必要。


推荐阅读