Search code examples
c#fluent-assertions

FluentAssertions fails with struct with enum but not class


I have a nested class and FluentAssertions can assert them.
Then I change class to struct and the test fails.

( If I change IEnumerable<ItemStruct> MyItems { get; set; } to ItemStruct MyItem { get; set; } the comparison succeeds in both cases. So I guess it has to do with the IEnumerable. )

using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;

namespace CowsCannotReadLogs.FileHandling.UnitTest
{
    [TestClass]
    public class TestFluentAssertionStruct
    {
        public struct DataStruct
        {
            public IEnumerable<string> MyItems { get; set; }
        }

        // Fails.
        [TestMethod]
        public void TestSimpleStruct()
        {
            var data1 = new DataStruct { MyItems = new[] { "A" } };
            var data2 = new DataStruct { MyItems = new[] { "A" } };
            data1.Should().BeEquivalentTo(data2);
        }

        // Fails.
        [TestMethod]
        public void TestSimpleStructWithComparingByValue()
        {
            var data1 = new DataStruct { MyItems = new[] { "A" } };
            var data2 = new DataStruct { MyItems = new[] { "A" } };
            data1.Should().BeEquivalentTo(data2, 
                options => options.ComparingByValue<DataStruct>());
        }


        public class DataClass
        {
            public IEnumerable<string> MyItems { get; set; }
        }

        // Succeeds.
        [TestMethod]
        public void TestSimpleClass()
        {
            var data1 = new DataClass { MyItems = new[] { "A" } };
            var data2 = new DataClass { MyItems = new[] { "A" } };
            data1.Should().BeEquivalentTo(data2);
        }
    }
}

Solution

  • When using BeEquivalentTo on structs, the two instances are by default compared by value semantics. to compare the structs by their members, the default behavior can be overridden either locally or globally.

    Locally inside a test:

    [TestMethod]
    public void Test()
    {
        subject.Should().BeEquivalentTo(expected, 
            opt => opt.ComparingByMembers<DataStruct>());
    }
    
    

    Globally in e.g. [AssemblyInitialize]:

    [AssemblyInitialize]
    public static void AssemblyInitialize(TestContext context)
    {
        AssertionOptions.AssertEquivalencyUsing(opt => opt.ComparingByMembers<DataStruct>());
    }