fluentassertions: BeEquivalentTo throws a NullReferenceException

Description

while running tests in parallel ( 2 threads) and when using BeEquivalentTo() to compare objects from two lists a null reference exception is thrown. However no NRE is thrown on using single thread

System.NullReferenceException : Object reference not set to an instance of an object.
   at FluentAssertions.Equivalency.SelfReferenceEquivalencyAssertionOptions`1.ToString()
public class Option
{
    public string Id { get; set; }
    public string Name { get; set; }
}
List<Option> expectedOptions;
List<Option> actualOptions;

Complete minimal example reproducing the issue

// Arrange
List<Option> expectedOptions = new List<Option>
{
    new Option()
    {
        Id = "4b71bcd9",
        Name = "AutoTest_123"
    }
};

// Act
List<Option> actualOptions = new List<Option>
{
    new Option()
    {
        Id = "4b71bcd9",
        Name = "AutoTest_123"
    }
};

// Assert
for (var i = 0; i < expectedOptions.Count; i++)
{
    expectedOptions [i].Should().BeEquivalentTo(actualOptions[i]);
}

Expected behavior:

The assertion should be true.

Actual behavior:

System.NullReferenceException : Object reference not set to an instance of an object.
   at FluentAssertions.Equivalency.SelfReferenceEquivalencyAssertionOptions`1.ToString()

Versions

FluentAssertions Version=“6.7.0”

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 16 (10 by maintainers)

Most upvoted comments

Thanks for the complete example, it made it a lot easier to diagnose.

ApiTestHelper.GlobalSetUp is invoked concurrently for both tests and does call AssertionOptions.AssertEquivalencyUsing which is not safe.

One way to solve it is to move the setup of Fluent Assertions into a Module Initializer which are guaranteed to only run once.

[System.Runtime.CompilerServices.ModuleInitializer]
internal static void SetupFluentAssertions()
{
    AssertionOptions.AssertEquivalencyUsing(options => options
        .Using<DateTimeOffset>(ctx => ctx.Subject.Should().BeSameDateAs(ctx.Expectation))
        .WhenTypeIs<DateTimeOffset>()
        .Using<DateTime>(ctx => ctx.Subject.Should().BeSameDateAs(ctx.Expectation))
        .WhenTypeIs<DateTime>()
    );
}

@jnyrup, Thanks a lot for digging into the problem resolving. I appreciate your help. It works now!