I have simple class, for example
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++;
}
}
And in test I wanna compare person I get from somewhere with expected Person like this:
var expectedPerson = new Person ("John","Galecky", new Person("Sheldon", "Cooper", null));
var actualPerson = PersonGenerator.GetCurrentPerson();
And I wanna to compare them recursively excluding Id field, what means for Parents too
actualPerson.Should().BeEquivalentTo(expectedPerson, (options) =>
{
options.Excluding(t => t.Id);
});
But ofc this works only for first level Person, how can I exclude Id field for Parent and for his Parent and e.t.c while FluentAssertion can go into recursion (10 levels in documentation)? In this Example it seems quite unreasonable, but I need exactly to do this, how it can be done?
To recursively exclude a member you'll have to use Excluding(Expression<Func<IMemberInfo, bool>> predicate)
which let's you pattern match the path to the member to exclude.
E.g. you want to exclude
As every path ends with Id
you can use
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")));
Be aware that this is pure string matching.
If e.g. another member has an Id
property you want to include, you can use this way to ensure that it only matches the root Id or any Parent.Id.
Regex.IsMatch(ctx.SelectedMemberPath, @"^(Parent\.)*Id$")