Fluents 断言:递归排除字段

Fluents Assertions: exclude field recursively

我有简单的class,例如

class Person {
   public string Name;
   public string LastName;
   public Person Parent;
   public static int IdCounter = 0;
   public int Id;

   public Person(string name, string lastName, Person parent) {
      Name = name;
      LastName = lastName;
      Parent = parent;
      Id = IdCounter++;
   }
}

在测试中,我想将我从某个地方得到的人与预期的人进行比较:

var expectedPerson = new Person ("John","Galecky", new Person("Sheldon", "Cooper", null));
var actualPerson = PersonGenerator.GetCurrentPerson();

我想递归地比较它们,不包括 Id 字段,Parents 也意味着什么

actualPerson.Should().BeEquivalentTo(expectedPerson, (options) =>
            {
                options.Excluding(t => t.Id);
            });

但是这仅适用于第一级人员,我如何排除 Parent 和他的 Parent 和 e.t.c 的 Id 字段,而 FluentAssertion 可以进入递归(10 级在文档中)? 在这个例子中似乎很不合理,但我确实需要这样做,如何才能做到?

要以递归方式排除成员,您必须使用 Excluding(Expression<Func<IMemberInfo, bool>> predicate) 让您模式匹配要排除的成员的路径。

例如你想排除

  • 编号
  • Parent.Id
  • Parent.Parent.Id
  • ...

由于每条路径都以 Id 结尾,您可以使用

Excluding(ctx => ctx.SelectedMemberPath.EndsWith("Id"))
var expectedPerson = new Person("John", "Galecky", new Person("Sheldon", "Cooper", null));
var actualPerson = new Person("John", "Galecky", new Person("Sheldon", "Cooper", null));

actualPerson.Should().BeEquivalentTo(expectedPerson, options =>
    options.Excluding(ctx => ctx.SelectedMemberPath.EndsWith("Id")));

请注意,这是纯字符串匹配。 如果例如另一个成员有一个 Id 属性 你 想要 包含,你可以使用这种方式来确保它只匹配根 ID 或任何 Parent.Id .

Regex.IsMatch(ctx.SelectedMemberPath, @"^(Parent\.)*Id$")