如何将嵌套在字典中的集合与 NUnit 进行比较?
How to compare sets that are nested in dictionaries with NUnit?
在较新版本的 NUnit 中,显然可以比较嵌套集合,如 this answer 所述。但是,这似乎不适用于嵌套的 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);
我预计它仍然会通过,因为 HashSet
是无序的,但测试失败了:
----> 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
是无序的,但 是 知道 Dictionary
是无序的。
所以我想我需要在某处使用 HashSet<string>.CreateSetComparer()
。我知道我可以指定用于与 Using
:
进行比较的相等比较器
Assert.That(a, Is.EqualTo(b).Using(someEqualityComparer));
但我试图提供它用于 嵌套 集合的比较。我该怎么做?
为了避免成为 XY 问题:我的真实代码中的字典实际上表示控制流图的边。它实际上是一个 Dictionary<BasicBlock, HashSet<BasicBlock>>
.
NUnit 并不完全“意识到”字典是无序的。但是,它确实有用于测试字典相等性的特殊代码,如 on this page 所述。您会注意到该页面没有说明任何关于哈希集的信息,哈希集没有得到特殊处理。
正如您所建议的,在您的示例中处理哈希集的最简单方法是定义您自己的比较器。我建议定义一个实现 IEqualityComparer<Hashset>
。这将自动解决嵌套问题,因为 NUnit 只会在到达嵌套哈希集时才使用该比较器。
如有必要,您可以重复Using
为不同类型创建多个比较器。但是,从你所说的来看,在这种情况下似乎没有必要。
在较新版本的 NUnit 中,显然可以比较嵌套集合,如 this answer 所述。但是,这似乎不适用于嵌套的 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);
我预计它仍然会通过,因为 HashSet
是无序的,但测试失败了:
----> 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
是无序的,但 是 知道 Dictionary
是无序的。
所以我想我需要在某处使用 HashSet<string>.CreateSetComparer()
。我知道我可以指定用于与 Using
:
Assert.That(a, Is.EqualTo(b).Using(someEqualityComparer));
但我试图提供它用于 嵌套 集合的比较。我该怎么做?
为了避免成为 XY 问题:我的真实代码中的字典实际上表示控制流图的边。它实际上是一个 Dictionary<BasicBlock, HashSet<BasicBlock>>
.
NUnit 并不完全“意识到”字典是无序的。但是,它确实有用于测试字典相等性的特殊代码,如 on this page 所述。您会注意到该页面没有说明任何关于哈希集的信息,哈希集没有得到特殊处理。
正如您所建议的,在您的示例中处理哈希集的最简单方法是定义您自己的比较器。我建议定义一个实现 IEqualityComparer<Hashset>
。这将自动解决嵌套问题,因为 NUnit 只会在到达嵌套哈希集时才使用该比较器。
如有必要,您可以重复Using
为不同类型创建多个比较器。但是,从你所说的来看,在这种情况下似乎没有必要。