如何在断言中排除EnumerableEquivalencyStep,仅验证对象属性?
问题
我有一个来自外部库的对象,该对象实现了IEnumerable<T>接口。我仅希望检查此对象的属性,而不验证集合的等价性,对IEnumerable内部的内容不感兴趣。请问如何在断言中排除这部分检查?
示例代码
public class Example : IEnumerable<string> { public string Id { get; set; } public string Name { get; set; } public IEnumerator<string> GetEnumerator() => new List<string> { Id }.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }
当前测试问题
当前测试会因IEnumerable部分的内容不匹配而失败:
(new Example {Id = "123", Name= "Test" } as object) .Should().BeEquivalentTo(new Example{Name = "Test"}, o => o.Excluding(p => p.Id));
现有方案的弊端
提前移除Enumerable等价性检查步骤可以解决问题,但会导致丢失检查类中任何IEnumerable类型属性的能力:
AssertionOptions.EquivalencyPlan.Remove<GenericEnumerableEquivalencyStep>(); AssertionOptions.EquivalencyPlan.Remove<EnumerableEquivalencyStep>();
解决方案
可以通过自定义等价性配置,针对特定类型(而非全局)跳过IEnumerable的集合校验,只检查对象的属性:
方法1:使用AsObjects()指定按对象属性比较
在BeEquivalentTo的配置中,通过AsObjects()告诉FluentAssertions将实现IEnumerable的实例当作普通对象处理,而不是集合:
(new Example { Id = "123", Name = "Test" } as object) .Should().BeEquivalentTo(new Example { Name = "Test" }, o => o.Excluding(p => p.Id) .AsObjects());
方法2:自定义等价性步骤(更灵活)
如果需要更精细的控制,可以添加自定义的等价性步骤,仅对目标类型跳过集合校验:
public class SkipExampleEnumerableCheck : IEquivalencyStep { public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) { // 仅对Example类型(或你需要的外部库类型)跳过集合校验 return context.Subject is Example && context.IsRootCollection; } public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) { // 按普通对象属性进行比较 parent.AssertEqualityUsing(context.ForNonEnumerable()); return true; } } // 在测试类初始化中添加该步骤 [TestInitialize] public void Setup() { AssertionOptions.EquivalencyPlan.InsertBefore<GenericEnumerableEquivalencyStep>(new SkipExampleEnumerableCheck()); }
这样既可以跳过目标对象的IEnumerable集合校验,又不会影响其他IEnumerable类型属性的正常断言。
内容的提问来源于stack exchange,提问作者Lodewijk
相关产品推荐
相关产品推荐

