Rogerio Schmitt
Rogerio Schmitt

Reputation: 1275

FluentAssertions won't exclude missing members on object graph comparison

I'm trying to compare a DTO with its respective entity using FluentAssertions object graph comparison. My entity has some extra metadata properties that my DTO does not have.

I'm trying to exclude these extra properties with the ExcludingMissingMembers options and even explicitly by excluding each member by itself like so:

result.Entity.Should().BeEquivalentTo(dto, opt => opt
  .ExcludingMissingMembers()
  .Excluding(x => x.ValidationResult)
  .Excluding(x => x.CreatedBy)
  .Excluding(x => x.CreatedAt));

But my test keeps failing because of the extra properties my DTO does not have.

Message: Expected result.Entity (of type Entity) to be

Entity
{
CreatedAt = <0001-01-01 00:00:00.000>
CreatedBy =
FinancialResourcesOrigins = {Labor, Labor}
ProductsOfInterest = {FixedIncome, FixedIncome}
ValidationResult =
}, but found

Dto
{
FinancialResourcesOrigins = {Labor, Labor}
ProductsOfInterest = {FixedIncome, FixedIncome}
}

With configuration:

  • Use declared types and members
  • Compare enums by value
  • Exclude member ValidationResult
  • Exclude member CreatedBy
  • Exclude member CreatedAt
  • Match member by name (or throw)
  • Be strict about the order of items in byte arrays
  • Without automatic conversion.

What am I missing here?

Upvotes: 0

Views: 1870

Answers (3)

randomCSharpDev
randomCSharpDev

Reputation: 1

FluentAssertions 6.8.0

actualValue.Should().BeEquivalentTo(expectedValue, options
            => options.Using(new IgnoreNullMembersInExpectation()));

public class IgnoreNullMembersInExpectation : IEquivalencyStep
{
    public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator)
    {
        if(comparands.Expectation is null)
        {
            return EquivalencyResult.AssertionCompleted;
        }

        return EquivalencyResult.ContinueWithNext;
    }
}

Upvotes: 0

Fabio
Fabio

Reputation: 32455

From source code of ExcludingMissingMembers():

Tries to match the members of the subject with equally named members on the expectation. Ignores those members that don't exist on the expectation and previously registered matching rules.

In your scenario "expectation" is a dto object, because entity(subject) have all properties from dto object, there are nothing to ignore.

You can achieve desired result by switching places of dto and entity

dto.Should().BeEquivalentTo(result.Entity, opt => opt.ExcludingMissingMembers());

After switching their places entity become an "expectation" and it's properties which is missing on the dto(subject) will be ignored

However this approach makes failing message a bit confusing, for example when result.Entity is null, message would be: Expected entity to be , but found Dto { .. }

Upvotes: 0

Danny Schneider
Danny Schneider

Reputation: 311

So, a fast test result:

var entity = new
    {
        CreatedAt = DateTime.Now,
        CreatedBy = "",
        FinancialResourcesOrigins = new[] { "Labor", "Labor" },
        ProductsOfInterest = new[] { "FixedIncome", "FixedIncome" },
        ValidationResult = ""
    };

var dto = new
    {
        FinancialResourcesOrigins = new[] { "Labor", "Labor" },
        ProductsOfInterest = new[] { "FixedIncome", "FixedIncome" },
    };


entity.Should()
     .BeEquivalentTo(dto, opt => opt
     .ExcludingMissingMembers());

This should work as expected.

Your mistake seems to be the explicit exclude, as the members (your variables x) are expected from your DTO, where they are not present

Upvotes: 0

Related Questions