Search code examples
c#.netfluent-assertions

Exclude EnumerableEquivalencyStep on top level Assertion


I have this object from an external library that implements IEnumerable<T>. I just want to check the properties of this object and not the equivalence of the collection. I'm not interested in the stuff inside the IEnumerable. How can I exclude this from the assertion?

public class Example : IEnumerable<string>
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IEnumerator<string> GetEnumerator() => new List<string> { Id }.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

This is the test, which will fail on the IEnumerable.

(new Example {Id = "123", Name= "Test" } as object)
    .Should().BeEquivalentTo(new Example{Name = "Test"},
        o => o.Excluding(p => p.Id));

Doing this before the test this will work, but then I lose the ability to check any IEnumerable property on the class:

AssertionOptions.EquivalencyPlan.Remove<GenericEnumerableEquivalencyStep>();
AssertionOptions.EquivalencyPlan.Remove<EnumerableEquivalencyStep>();

Solution

  • One way to workaround this limitation is to add a dedicated equivalency step to handle Example.

    using FluentAssertions;
    using FluentAssertions.Equivalency;
    using FluentAssertions.Equivalency.Steps;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    
    [TestClass]
    public class UnitTest1
    {
        [ModuleInitializer]
        public static void SetDefaults()
        {
            AssertionOptions.EquivalencyPlan.Insert<ExampleEquivalencyStep>();
        }
    
        [TestMethod]
        public void TestMethod1()
        {
            object subject = new Example { Id = "123", Name = "Test" };
            var expected = new Example { Name = "Test" };
            subject.Should().BeEquivalentTo(expected, o => o.Excluding(p => p.Id));
        }
    }
    
    class ExampleEquivalencyStep : EquivalencyStep<Example>
    {
        protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) =>
            new StructuralEqualityEquivalencyStep().Handle(comparands, context, nestedValidator);
    }
    
    public class Example : IEnumerable<string>
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public IEnumerator<string> GetEnumerator() => new List<string> { Id }.GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }