如何将嵌套在字典中的集合与 NUnit 进行比较?

How to compare sets that are nested in dictionaries with NUnit?

在较新版本的 NUnit 中,显然可以比较嵌套集合,如 this answer 所述。但是,这似乎不适用于嵌套的 HashSets。考虑:

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 为不同类型创建多个比较器。但是,从你所说的来看,在这种情况下似乎没有必要。