You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FluentAssertions中递归排除所有IDto的Id属性

解决FluentAssertions中排除所有层级IDto的Id属性问题

你可以利用FluentAssertions的ExcludingMembersThat方法,结合类型判断实现全局排除所有层级IDto接口的Id属性,无需手动反射遍历嵌套对象。

核心思路

ExcludingMembersThat会递归遍历所有层级的属性(包括嵌套对象的属性),只需判断当前成员所属类型是否实现了IDto且属性名为Id,即可统一排除。

代码示例

首先定义你的Dto接口和实体:

public interface IDto
{
    int Id { get; set; }
}

public class SampleDto : IDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ComplexDto : IDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public SampleDto NestedDto { get; set; }
}

测试中的使用方式

直接在等价性断言中配置排除规则:

var expected = new ComplexDto 
{ 
    Title = "Test", 
    NestedDto = new SampleDto { Name = "Nested" } 
};

var actual = new ComplexDto 
{ 
    Id = 1, 
    Title = "Test", 
    NestedDto = new SampleDto { Id = 2, Name = "Nested" } 
};

// 排除所有层级的IDto.Id属性
actual.Should().BeEquivalentTo(expected, options =>
    options.ExcludingMembersThat(member => 
        member.DeclaringType?.GetInterfaces().Contains(typeof(IDto)) == true && 
        member.Name == nameof(IDto.Id)));

封装成扩展方法(复用性更强)

为避免重复编写规则,可封装成扩展方法:

public static class FluentAssertionsDtoExtensions
{
    public static EquivalencyAssertionOptions<T> ExcludeAllDtoIds<T>(this EquivalencyAssertionOptions<T> options)
    {
        return options.ExcludingMembersThat(member => 
            member.DeclaringType?.GetInterfaces().Contains(typeof(IDto)) == true && 
            member.Name == nameof(IDto.Id));
    }
}

之后测试时直接调用:

actual.Should().BeEquivalentTo(expected, options => options.ExcludeAllDtoIds());

这种方式完全依赖FluentAssertions自身的递归遍历机制,无需手动实现反射逻辑,既优雅又能覆盖所有嵌套层级的Id属性排除需求。

内容的提问来源于stack exchange,提问作者Robert Schmidt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:10:29