C# 如何在集合中的属性的FluentAssertions中使用Exclude?

C# 如何在集合中的属性的FluentAssertions中使用Exclude?,c#,unit-testing,fluent-assertions,C#,Unit Testing,Fluent Assertions,我有两门课: public class ClassA { public int? ID {get; set;} public IEnumerable<ClassB> Children {get; set;} } public class ClassB { public int? ID {get; set;} public string Name {get; set;} } 很明显,我可以对集合中的每个ClassB重复这一点。然而,我正在寻找一种排除所有ID的方法(

我有两门课:

public class ClassA
{
  public int? ID {get; set;}
  public IEnumerable<ClassB> Children {get; set;}
}

public class ClassB
{
  public int? ID {get; set;}
  public string Name {get; set;}
}
很明显,我可以对集合中的每个ClassB重复这一点。然而,我正在寻找一种排除所有ID的方法(而不是对每个元素进行排除)

但是,我已经读过,如果删除[0]索引器,断言将失败


这可能吗?

简单的方法是直接在集合上设置断言,并在
ClassA
等价断言上排除断言:

expectedA.ShouldBeEquivalentTo(expectedB,
   o => o.Excluding(s => s.PropertyInfo.Name == "Children"));
expectedA.Children.ShouldBeEquivalentTo(expectedB.Children,
   o => o.Excluding(s => s.PropertyInfo.Name = "Id"));
那怎么办

expected.ShouldBeEquivalentTo(actualA, options => options.Excluding(su => 
   (su.RuntimeType == typeof(ClassB)) && (su.PropertyPath.EndsWith("Id")));`
或者可以在属性路径上进行正则表达式匹配,例如

expected.ShouldBeEquivalentTo(actualA, options => options.Excluding(su => (Regex.IsMatch
   ("Children\[.+\]\.ID"));
实际上我喜欢最后一个,但是正则表达式的东西让它有点难读。也许我应该使用一种方法来扩展
ISubjectInfo
,使路径与通配符模式相匹配,以便您可以执行以下操作:

expectedA.ShouldBeEquivalentTo(actualA, options => options.Excluding(x => x.PropertyPath == "Children[0].ID"));
expected.ShouldBeEquivalentTo(actualA, options => options
  .Excluding(su => su.PathMatches("Children[*].ID")));

我刚刚遇到了一个类似的问题,最新版本的FluentAssertions稍微改变了一些情况

“我的对象”包含其他对象的词典。字典中的对象包含我要排除的其他对象。我的场景是关于测试Json序列化的,我忽略了某些属性

这对我很有用:

gotA.ShouldBeEquivalentTo(expectedB , config => 
  config
    .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Venue))
    .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Exhibit))
    .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Content))
    .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Survey))
    .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Media))
  );
花了一些时间研究如何做,但它真的很有用

最简单的方法是:

expected.ShouldBeEquivalentTo(实际,配置=>config.ExcludingMissingMembers());

基于我的正则表达式匹配思想,我能够让它工作

expected.ShouldBeEquivalentTo(actualA, options =>
  options.Excluding(su => 
     (Regex.IsMatch(su.SelectedMemberPath, "Children\\[.+\\].ID"));

与Dennis答案的不同之处在于:传递su.SelectedMemberPath,使用双反斜杠来转义方括号。

一个扩展类,可以在其中传递表达式列表

public static class FluentAssertionsExtensions {
    public static EquivalencyAssertionOptions<T> ExcludingNextProperties<T>(
        this EquivalencyAssertionOptions<T> options,
        params Expression<Func<T, object>>[] expressions) {
        foreach (var expression in expressions) {
            options.Excluding(expression);
        }

        return options;
    }
}

应该等价于
方法现在似乎已经过时,为了获取的路径,您可以使用
排除
重载和
IMemberInfo。改为选择成员路径

expected.Should().BeEquivalentTo(actualA, options => 
    options.Excluding((IMemberInfo mi) => mi.SelectedMemberPath.EndsWith("ID")));

我认为语法是这样的

       actual.Should().BeEquivalentTo(
        expected, 
        config => config.Excluding(o => o.Id).Excluding(o => o.CreateDateUtc) });

我将把这个标记为答案,因为扩展方法中的正则表达式是我最后使用的方法,在更新版本的FluentAssertions中这有什么变化?我不确定
PropertyPath
是否仍然存在。我尝试了两个选项都没有成功,但能够修复RegEx选项以使用当前版本-请参阅。顺便说一句,PropertyPath的新名称是SelectedMemberPath
Regex.IsMatch(x.SelectedMemberPath,@“Children\[\d+\]\.ID”)
OP要求排除一些现有(未丢失)成员。我认为Propertyinfo不再存在。SelectedMemberInfo.Name应该这样做。出于价值考虑,您也可以传入一个匿名对象作为自FA 5以来的期望值,并且只包含您关心的属性。不是所有的英雄都会这样做
       actual.Should().BeEquivalentTo(
        expected, 
        config => config.Excluding(o => o.Id).Excluding(o => o.CreateDateUtc) });