Description
Description
I noticed the implementation for IsEquivarentTo in TypeExtensions considers two members to be equivalent if they have the same name and the declaring type of either property is the same or inherits the type of the other property. This is incorrect due to member hiding.
Complete minimal example reproducing the issue
E.g.
void Main()
{
var aProperty = SelectedMemberInfo.Create(typeof(A).GetProperty("Property"));
var bProperty = SelectedMemberInfo.Create(typeof(B).GetProperties().First(p => p.DeclaringType == typeof(B)));
aProperty.IsEquivalentTo(bProperty).Should().BeFalse();
B b1 = new B(), b2 = new B();
b1.Should().BeEquivalentTo(b2, config => config.Including(b => b.Property));
}
class A
{
public string Property { get; set; } = Guid.NewGuid().ToString();
}
class B: A
{
public new string[] Property { get; set; }
}
Expected behavior:
Main
should execute successfully, because the two properties are different and the two instances of B
are equivalent when comparing only the null arrays.
Actual behavior:
Both assertions throw because of the logic error in IsEquivalentTo
. The second assertion throws because the logic for BeEquivalentTo
gets the property from the expression and then uses IsEquivalentTo
to compare it against other properties later.
Versions
- Which version of Fluent Assertions are you using? 5.4.2
- Which .NET runtime and version are you targeting? .NET Framework 4.7.2
Additional Information
Using Excluding(b => ((A)b).Property)
instead of Including(b => b.Property)
does not work either because the code for extracting the member from the expression does not support casts.