FluentAssertions fails with struct with enum but not class
Asked Answered
T

1

5

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);
        }
    }
}
Triangle answered 4/4, 2019 at 19:56 Comment(3)
If you check FluentAssertion's documentation ("Object graph comparison") you'll see that the method BeEquivalentTo compares two instances by value semantics, checking each one of it's properties if the type being compared overrides Obejct.Equal. This is not true for your value types, so they will be compared with the default equality operator for value types, which will succeed if your struct only has other struct properties but will fail when you have a reference type (IEnumerable) as one of its properties. I suspect that using ComparingByValue<DataStruct> would solve it.Basipetal
@Basipetal Thanks for the ComparingByValue<> information. It still does not work though. I updated the example.Triangle
Try using ComparingByMembers<DataStruct>() instead.Crustal
C
7

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>());
}

Crustal answered 6/4, 2019 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.