如何用FluentAssertions实现C#嵌套集合的深度相等比较?
问题:嵌套集合的单元测试相等性判定
编写单元测试时遇到以下问题:如何让两个结构完全一致的嵌套集合对象被判定为相等?同时要确保任意深度的嵌套集合按List的索引位置、Dictionary的匹配键进行对等比较。使用FluentAssertions库编写测试代码后出现错误。
代码示例
List<Dictionary<List<string>, string>> list1 = new(){ new (){{new (){"a"}, "aaa"}, {new (){"z"}, "zzz"}}, new (){{new (){"b"}, "bbb"}}, new (){{new (){"c"}, "ccc"}} }; List<Dictionary<List<string>, string>> list2 = new(){ new (){{new (){"a"}, "aaa"}, {new (){"z"}, "zzz"}}, new (){{new (){"b"}, "bbb"}}, new (){{new (){"c"}, "ccc"}} }; list1.Should().BeEquivalentTo(list2);
错误信息
未处理的异常:FluentAssertions.Execution.AssertionFailedException:预期list1[0]是包含2个项的字典,但它缺少键{{"a"}, {"z"}}且存在额外键{{"b"}} 预期list1[1]包含键{"b"}。 预期list1[2]包含键{"c"}。 配置信息: - 使用声明的类型和成员 - 按值比较枚举 - 按属性比较元组 - 按属性比较匿名类型 - 按成员比较记录 - 包含不可浏览成员 - 包含所有非私有属性 - 包含所有非私有字段 - 按名称匹配成员(不匹配则抛出) - 严格要求字节数组中项的顺序 - 不自动转换。
解决方案
问题根源在于Dictionary的键是List
要解决这个问题,需配置FluentAssertions对作为字典键的集合类型按内容比较,同时保持List的顺序匹配、字典的键值对对应:
- 自定义比较规则,指定
List<string>类型使用结构相等性比较 - 确保List严格按索引顺序比较,字典按键匹配对应的值
方案1:直接配置FluentAssertions规则
修改后的测试代码:
list1.Should().BeEquivalentTo(list2, options => options .Using<List<string>>(ctx => ctx.Subject.Should().BeEquivalentTo(ctx.Expectation)) .WhenTypeIs<List<string>>() .WithStrictOrdering()); // 强制List按索引顺序比较
方案2:通用嵌套集合配置(适用于任意深度)
list1.Should().BeEquivalentTo(list2, options => options .ForAllCollections(c => c.WithStrictOrdering()) // 所有集合类型严格按顺序 .Using<ICollection>(ctx => ctx.Subject.Should().BeEquivalentTo(ctx.Expectation)) .WhenTypeIs<ICollection>());
方案3:自定义相等比较器
先实现针对List<string>的相等比较器:
public class ListStringEqualityComparer : IEqualityComparer<List<string>> { public bool Equals(List<string>? x, List<string>? y) { if (x == null && y == null) return true; if (x == null || y == null) return false; return x.SequenceEqual(y); } public int GetHashCode(List<string> obj) { int hash = 17; foreach (var item in obj) { hash = hash * 31 + (item?.GetHashCode() ?? 0); } return hash; } }
然后在测试中使用该比较器:
list1.Should().BeEquivalentTo(list2, options => options .WithDictionaryKeyComparer(new ListStringEqualityComparer()) .WithStrictOrdering());
内容的提问来源于stack exchange,提问作者AffluentOwl
相关产品推荐
相关产品推荐

