Reputation: 2401
I'm testing complicated object graphs with FluentAssertions and I want to set defaults for ShouldBeEquivalentTo
. The problem is that the object graph re-used the same base-type for a lot of the properties. I just want to set up my AssertionOptions
s once per Type but I can't seem to find out how.
Example: I have this object graph:
public class Inner
{
public string One { get; set; }
public string Two { get; set; }
}
public class Outer : Inner
{
public Inner Inner { get; set; }
}
I set up a Custom Extension:
public AndConstraint<InnerAssertions<T>> BeEquivalentTo(T expectation)
{
return base.BeEquivalentTo(expectation,
c => c
.RespectingRuntimeTypes()
.Excluding(r => r.Two));
}
Now I want this test to pass:
new Outer
{
One = "1",
Two = "2",
Inner = new Inner {One = "inner.1", Two = "inner.2"}
}.Should()
.BeEquivalentTo(new Outer
{
One = "1",
Two = "3",
Inner =new Inner {One = "inner.1", Two = "inner.3"}
});
This obviously fails on root.Inner.Two
, but I hope this makes clear what I want to do.
Upvotes: 0
Views: 186
Reputation: 8909
Another way to avoid this situation is to pass an anonymous type to BeEquivalentTo
that only includes the properties that you care about in those specific tests.
Upvotes: 0
Reputation: 2586
One way to achieve this is by using an IMemberSelectionRule
to exclude Inner.Two
from equivalency comparisons
class ExcludeTwo : IMemberSelectionRule
{
public bool IncludesMembers => false;
public IEnumerable<IMember> SelectMembers(INode currentNode, IEnumerable<IMember> selectedMembers, MemberSelectionContext context) =>
selectedMembers.Where(e => !(e.DeclaringType == typeof(Inner) && e.Name == nameof(Inner.Two)));
}
and then add it to the stat AssertionOptions
with e.g. a ModuleInitializer
.
[ModuleInitializer]
public static void SetDefaults()
{
AssertionOptions.AssertEquivalencyUsing(e => e.Using(new ExcludeTwo()));
}
Upvotes: 0