FluentAssertions自定义EquivalencyStep如何正确打印属性上下文
自定义FluentAssertions EquivalencyStep中属性名称错误显示的解决方法
问题背景
自定义PaginatedList<T>继承自List<T>并实现IPaginatedList接口扩展分页属性,使用FluentAssertions的BeEquivalentTo()时,默认只对比集合内容忽略分页属性。因此编写了PaginatedListEquivalencyStep手动验证这些属性,但验证失败时错误消息中的属性名称显示混乱,仅在添加.WithTrace()后才正常显示正确路径。
原因分析
这不是FluentAssertions的Bug,而是自定义EquivalencyStep的用法存在疏漏:
- 手动拼接
AssertionScope的描述文本时,没有利用FluentAssertions内置的路径管理机制,导致手动拼接的文本与上下文自动追踪的路径发生叠加,生成了混乱的错误消息。 .WithTrace()启用了详细路径追踪,临时覆盖了手动拼接的错误,但这并非正确的解决方式。
解决方案
正确的做法是利用验证上下文的CreateChildNode方法生成子属性的路径节点,让FluentAssertions自动维护属性路径,避免手动拼接带来的混乱。
修改后的PaginatedListEquivalencyStep实现
public sealed class PaginatedListEquivalencyStep : EquivalencyStep<IPaginatedList> { protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Subject is not IPaginatedList subject) throw new NotSupportedException(); if (comparands.Expectation is not IPaginatedList expectation) throw new NotSupportedException(); // 为每个分页属性创建子节点,让FluentAssertions自动管理路径 ValidatePaginatedProperty(subject.ItemsCount, expectation.ItemsCount, nameof(IPaginatedList.ItemsCount), context, nestedValidator); ValidatePaginatedProperty(subject.CurrentPage, expectation.CurrentPage, nameof(IPaginatedList.CurrentPage), context, nestedValidator); ValidatePaginatedProperty(subject.PageSize, expectation.PageSize, nameof(IPaginatedList.PageSize), context, nestedValidator); // 验证集合内容 new EnumerableEquivalencyStep().Handle(comparands, context, nestedValidator); return EquivalencyResult.AssertionCompleted; } private static void ValidatePaginatedProperty(int subjectValue, int expectationValue, string propertyName, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var propertyComparands = new Comparands(subjectValue, expectationValue, context.Options); var childNode = context.CreateChildNode(propertyName); nestedValidator.AssertEquality(propertyComparands, childNode); } }
或者,若仍想使用AssertionScope,需通过CreateChildNode获取正确的属性路径:
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Subject is not IPaginatedList subject) throw new NotSupportedException(); if (comparands.Expectation is not IPaginatedList expectation) throw new NotSupportedException(); var itemsCountNode = context.CreateChildNode(nameof(IPaginatedList.ItemsCount)); using (new AssertionScope(itemsCountNode.Description)) { subject.ItemsCount.Should().Be(expectation.ItemsCount); } var currentPageNode = context.CreateChildNode(nameof(IPaginatedList.CurrentPage)); using (new AssertionScope(currentPageNode.Description)) { subject.CurrentPage.Should().Be(expectation.CurrentPage); } var pageSizeNode = context.CreateChildNode(nameof(IPaginatedList.PageSize)); using (new AssertionScope(pageSizeNode.Description)) { subject.PageSize.Should().Be(expectation.PageSize); } new EnumerableEquivalencyStep().Handle(comparands, context, nestedValidator); return EquivalencyResult.AssertionCompleted; }
验证效果
修改后运行测试代码,错误消息将正常显示:
Expected property result.ValueOrDefault.ItemsCount to be 10, but found 3 (difference of -7)
内容的提问来源于stack exchange,提问作者user26719255
相关产品推荐
相关产品推荐

