Skip to content

Inherited property cannot be excluded or included when comparing interface collections using runtime types #1363

@aayjaychan

Description

@aayjaychan

Description

When a derive class implements an interface through an inherited property, the property cannot be excluded by .Excluding() or included by .Including() when comparing collections of the interface using runtime types.

Complete minimal example reproducing the issue

public interface Interface
{
    int Value1 { get; set; }
    int Value2 { get; set; }
}

public class Base
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }
}

public class Derived : Base, Interface
{
}

[Test]
public void Exclude()
{
    var actual = new Interface[]
    {
        new Derived() { Value1 = 1, Value2 = 2 }
    };
    var expected = new Interface[]
    {
        new Derived() { Value1 = 999, Value2 = 2 }
    };

    actual.Should().BeEquivalentTo(
        expected,
        options => options
            .Excluding(a => a.Value1)
            .RespectingRuntimeTypes());
}

[Test]
public void Include()
{
    var actual = new Interface[]
    {
        new Derived() { Value1 = 1, Value2 = 2 }
    };
    var expected = new Interface[]
    {
        new Derived() { Value1 = 999, Value2 = 2 }
    };

    actual.Should().BeEquivalentTo(
        expected,
        options => options
            .Including(a => a.Value2)
            .RespectingRuntimeTypes());
}

Expected behavior:

Both tests pass

Actual behavior:

Exclude fails with

  Error Message:
   Expected item[0].FromBase to be 999, but found 1.                     

With configuration:                                                      
- Use runtime types and members                                          
- Compare enums by value                                                 
- Include all non-private properties                                     
- Include all non-private fields                                         
- Exclude member root.FromBase                                           
- Match member by name (or throw)                                        
- Be strict about the order of items in byte arrays                      
- Without automatic conversion. 

  Stack Trace:                                                           
     at FluentAssertions.Execution.LateBoundTestFramework.Throw(String message)                                                                   
   at FluentAssertions.Execution.TestFrameworkProvider.Throw(String message)                                                                      
   at FluentAssertions.Execution.CollectingAssertionStrategy.ThrowIfAny(IDictionary`2 context)                                                    
   at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(EquivalencyValidationContext context)                                      
   at FluentAssertions.Collections.CollectionAssertions`2.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, Func`2 config, String because, Object[] becauseArgs)

Include fails with

  Error Message:
   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.GenericEnumerableEquivalencyStep.Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
   at FluentAssertions.Equivalency.EquivalencyValidator.RunStepsUntilEquivalencyIsProven(IEquivalencyValidationContext context)
   at FluentAssertions.Equivalency.EquivalencyValidator.AssertEqualityUsing(IEquivalencyValidationContext context)
   at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(EquivalencyValidationContext context)
   at FluentAssertions.Collections.CollectionAssertions`2.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, Func`2 config, String because, Object[] becauseArgs)

Versions

FluentAssertions 5.10.3 and 6.0.0-alpha.1
NUnit 3.12.0
.NET Core 3.1

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions