Search code examples
c#fluent-assertions

C# Fluent Assertions global options for ShouldBeEquivalentTo


In Fluent Assertions when comparing objects with DateTime properties there are sometimes a slight mismatch in the milliseconds and the comparison fail. The way we get around it is to set the comparison option like so:

actual.ShouldBeEquivalentTo(expected,
        options =>
            options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation))
                .WhenTypeIs<DateTime>());

Is there a way to set this up once and have it always apply instead of having to specify it every time we call ShouldBeEquivalentTo?

Update1: Tried the following approach but it doesn't seem to work, test fails on 1 millisecond difference. The new default does not seem to get called by the factory.

using System;
using FluentAssertions;
using FluentAssertions.Equivalency;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    class Test
    {
        public DateTime TestDateTime { get; set; }
    }

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void SettingFluentAssertionDefault()
        {
            // arrange
            var defaultAssertionOptions = EquivalencyAssertionOptions<DateTime>.Default;

            EquivalencyAssertionOptions<DateTime>.Default = () =>
            {
                var config = defaultAssertionOptions();
                config.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
                return config;
            };

            var testDateTime = DateTime.Now;
            var expected = new Test {TestDateTime = testDateTime};

            // act
            var actual = new Test {TestDateTime = testDateTime.AddMilliseconds(1)};

            // assert
            actual.ShouldBeEquivalentTo(expected);
        }
    }
}

Solution

  • Actually, you can. The default configuration factory is exposed by the static property EquivalencyAssertionOptions<Test>.Default. You can easily assign an alternative configuration for a particular data type, or extend the default configuration with additional behavior. Something like:

    var defaultAssertionOptions = EquivalencyAssertionOptions<Test>.Default;
    
    EquivalencyAssertionOptions<Test>.Default = () =>
    {
        var config = defaultAssertionOptions();
        config.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
        return config;
    };
    

    If you want you can get the current default and tuck that away in some variable that you use from your factory method.