Exception thrown when comparing empty types using 'BeEquivalentTo' with 'RespectingRuntimeTypes' set
See original GitHub issueDescription
I have a scenario where I need to compare a response object against an expected object, and I’m using source.Should().BeEquivalentTo(target)
for that.
However, I hit a situation where I believe the library has a poor default: when the objects being compared have no declared members and you only want to ensure that the types match.
I tried to “correct” what I thought was a mistake on my part, by setting the RespectingRuntimeTypes()
option. This has not changed the result however.
Complete minimal example reproducing the issue
Say I have some interface/base class defining a set of possible values, something like:
public abstract class SomeResponse
{
}
public sealed class NotFoundResponse : SomeResponse
{
}
public sealed class ValidResponse : SomeResponse
{
public ValidResponse(int value)
{
this.Value = value;
}
public int Value { get; }
}
Notice how one of the response types has no properties, while the other has a single property.
Now, if I attempt to compare some response variable, and it happens to be NotFoundResponse
, I get an exception:
// Arrange (fake values)
SomeResponse response = new NotFoundResponse();
SomeResponse expectedResponse = new NotFoundResponse();
// Assert
response.Should().BeEquivalentTo(expectedResponse, c => c.RespectingRuntimeTypes());
Expected behavior:
I think it would be best if the comparison succeeded when both objects have no properties but are of the same runtime type if the RespectingRuntimeTypes
setting is used.
Actual behavior:
The following exception is thrown:
System.InvalidOperationException : No members were found for comparison. Please specify some members to include in the comparison or choose a more meaningful assertion.
Stack Trace:
at FluentAssertions.Equivalency.Steps.StructuralEqualityEquivalencyStep.Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator)
at FluentAssertions.Equivalency.EquivalencyValidator.RunStepsUntilEquivalencyIsProven(Comparands comparands, IEquivalencyValidationContext context)
at FluentAssertions.Equivalency.EquivalencyValidator.RecursivelyAssertEquality(Comparands comparands, IEquivalencyValidationContext context)
at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands comparands, EquivalencyValidationContext context)
at FluentAssertions.Primitives.ObjectAssertions`2.BeEquivalentTo[TExpectation](TExpectation expectation, Func`2 config, String because, Object[] becauseArgs)
Versions
FA v6.5.1 .NET 6
Additional Information
Note that changing the comparison to something more specific (like BeOfType
) would change the meaning of the comparison and is not a substitute: I need to also compare the properties when they are available.
I think it only makes sense to throw this exception if types are excluded from the comparison, but even then, it is questionable whether or not it wouldn’t be better to also return true
when both sides have no members.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:5 (3 by maintainers)
Top GitHub Comments
Yep. Added that to the v7 list.
Ah, this is where the misunderstanding is coming from.
RespectingRuntimeTypes
is just an option to tell FA to look at the run-time type of the object when looking for members to compare instead of the declared type. FA never cares about the type of the object’s type themselves. That’s what we are trying to accomplish using https://github.com/fluentassertions/fluentassertions/pull/1704