【问题标题】:How to compare sets that are nested in dictionaries with NUnit?如何将嵌套在字典中的集合与 NUnit 进行比较?
【发布时间】:2021-08-22 01:23:27
【问题描述】:

在较新版本的 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&lt;string&gt;.CreateSetComparer()。我知道我可以指定用于与Using 进行比较的相等比较器:

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

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

为了避免出现 XY 问题:我的真实代码中的字典实际上代表了控制流图的边缘。实际上是Dictionary&lt;BasicBlock, HashSet&lt;BasicBlock&gt;&gt;

【问题讨论】:

  • 它把HashSet 当作一个enumerable 来处理顺序很重要,你可能已经猜到了。如果您将HashSet 更改为SortedSet(例如Dictionary&lt;string, SortedSet&lt;string&gt;),您可能会得到您期望的结果。但是,可能不适合您想要的。
  • @TheGeneral 感谢您提醒我SortedSet 的存在!就我而言,我可以BasicBlock 写一个IComparer,所以我认为可以使用SortedSet。不过,我仍然对更通用的解决方案持开放态度:)

标签: c# nunit hashset


【解决方案1】:

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

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

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

【讨论】:

  • 哦!所以即使我说Is.EqualTo(someDictionary),我仍然可以说.Using(someHashSetEqualityComparer),它只会在比较嵌套集时使用那个相等比较器?我很惊讶Using 如此聪明。这在任何地方都有记录吗?我想知道为什么我在这上面找不到任何东西...
  • 它记录在我引用的页面上,尽管可能没有解释得很清楚。请注意,这仅在您的比较器实现IEqualityComparer&lt;HashSet&gt; 时才有效。 NUnit 使用通用参数来决定何时应用它。公平警告:我编写了代码,我知道它可以工作(经过测试),但我不知道自从我使用 NUnit 以来是否有任何变化。
猜你喜欢
  • 1970-01-01
  • 2021-05-22
  • 2014-09-14
  • 1970-01-01
  • 2019-09-30
  • 2018-07-17
  • 2020-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多