如何在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
相关产品推荐
相关产品推荐

