How can you elegantly assert the following kind of equivalence between two .NET objects (ideally using the Fluent Assertions library)?
Two objects are structurally equivalent if:
Note that subject.Should().BeEquivalentTo(expectation)
does not work since BeEquivalentTo
does not check type equality. For example, if we have two classes A
and B
each with a single property object X { get; set; }
, then the two objects
new A { X = new B { X = new A() }}
and
new B { X = new A { X = new B() }}
would be deemed equivalent by BeEquivalentTo
, even though their types and the types of their properties and subproperties do not match, and hence are not structurally equivalent by the above definition.
I came up with this solution, but I would have hoped there was a more elegant one.
Define a custom IEquivalencyStep
:
public class StrictTypeEquivalence : IEquivalencyStep
{
public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
{
return context.Subject != null && context.Expectation != null &&
context.Subject.GetType() != context.Expectation.GetType();
}
public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
{
throw new AssertionFailedException($"{context.SelectedMemberPath}: Expected type {context.Expectation.GetType()} but found {context.Subject.GetType()} instead.");
}
}
And then check equivalence like so:
subject.Should().BeEquivalentTo(expectation, options => options.Using(new StrictTypeEquivalence()));