Skip to content

Null reference exception when using custom comparer in equivalency options #2595

@SvetlanaBurlakova

Description

@SvetlanaBurlakova

Description

Look at the code below. The second test fails with unexpected NRE.
I'm using the latest alpha version: 7.0.0-alpha.3
.Net 6

using NUnit.Framework;

namespace UnitTests;

public class FluentAssertionsEquivalencyFailureTest
{
    [Test]
    public void Success()
    {
        var expected = new TestClass();
        var actual = new TestClass() { NullableField = DateTime.UtcNow };

        FluentActions.Invoking(() => actual.Should().BeEquivalentTo(expected))
            .Should()
            .Throw<AssertionException>()
            .WithMessage("Expected property actual.NullableField to be <null>, but found <*>.*");
    }

    [Test]
    public void NullReferenceFailure()
    {
        var expected = new TestClass();
        var actual = new TestClass() { NullableField = DateTime.UtcNow };

        FluentActions.Invoking(() => actual.Should().BeEquivalentTo(expected, o => o.Using(EqualityComparer<DateTime>.Default)))
            .Should()
            .Throw<AssertionException>()
            .WithMessage("Expected property actual.NullableField to be <null>, but found <*>.*");
        
        /*
Expected a <NUnit.Framework.AssertionException> to be thrown, but found <System.NullReferenceException>: "
"System.NullReferenceException with message "Object reference not set to an instance of an object."
     at FluentAssertions.Equivalency.Steps.EqualityComparerEquivalencyStep`1.<>c__DisplayClass2_0.<Handle>b__0() in /_/Src/FluentAssertions/Equivalency/Steps/EqualityComparerEquivalencyStep.cs:line 28
     at FluentAssertions.Execution.GivenSelector`1..ctor(Func`1 selector, AssertionScope predecessor, Boolean continueAsserting) in /_/Src/FluentAssertions/Execution/GivenSelector.cs:line 23
     at FluentAssertions.Execution.AssertionScope.Given[T](Func`1 selector) in /_/Src/FluentAssertions/Execution/AssertionScope.cs:line 214
     at FluentAssertions.Execution.ContinuedAssertionScope.Given[T](Func`1 selector) in /_/Src/FluentAssertions/Execution/ContinuedAssertionScope.cs:line 28
     at FluentAssertions.Equivalency.Steps.EqualityComparerEquivalencyStep`1.Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) in /_/Src/FluentAssertions/Equivalency/Steps/EqualityComparerEquivalencyStep.cs:line 23
     at FluentAssertions.Equivalency.Steps.RunAllUserStepsEquivalencyStep.Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) in /_/Src/FluentAssertions/Equivalency/Steps/RunAllUserStepsEquivalencyStep.cs:line 11
     at FluentAssertions.Equivalency.EquivalencyValidator.RunStepsUntilEquivalencyIsProven(Comparands comparands, IEquivalencyValidationContext context) in /_/Src/FluentAssertions/Equivalency/EquivalencyValidator.cs:line 69
     at FluentAssertions.Equivalency.EquivalencyValidator.RecursivelyAssertEquality(Comparands comparands, IEquivalencyValidationContext context) in /_/Src/FluentAssertions/Equivalency/EquivalencyValidator.cs:line 39
     at FluentAssertions.Equivalency.Steps.StructuralEqualityEquivalencyStep.AssertMemberEquality(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator parent, IMember selectedMember, IEquivalencyAssertionOptions options) in /_/Src/FluentAssertions/Equivalency/Steps/StructuralEqualityEquivalencyStep.cs:line 72
     at FluentAssertions.Equivalency.Steps.StructuralEqualityEquivalencyStep.Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) in /_/Src/FluentAssertions/Equivalency/Steps/StructuralEqualityEquivalencyStep.cs:line 45
     at FluentAssertions.Equivalency.EquivalencyValidator.RunStepsUntilEquivalencyIsProven(Comparands comparands, IEquivalencyValidationContext context) in /_/Src/FluentAssertions/Equivalency/EquivalencyValidator.cs:line 69
     at FluentAssertions.Equivalency.EquivalencyValidator.RecursivelyAssertEquality(Comparands comparands, IEquivalencyValidationContext context) in /_/Src/FluentAssertions/Equivalency/EquivalencyValidator.cs:line 39
     at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands comparands, EquivalencyValidationContext context) in /_/Src/FluentAssertions/Equivalency/EquivalencyValidator.cs:line 21
     at FluentAssertions.Primitives.ObjectAssertions`2.BeEquivalentTo[TExpectation](TExpectation expectation, Func`2 config, String because, Object[] becauseArgs) in /_/Src/FluentAssertions/Primitives/ObjectAssertions.cs:line 145
     at UnitTests.FluentAssertionsEquivalencyFailureTest.<>c__DisplayClass1_0.<NullReferenceFailure>b__0() in C:\Telgorithm\src\phone\tmp\My.UnitTests\FluentAssertionsFailureTest.cs:line 25
     at FluentAssertions.Specialized.FunctionAssertions`1.InvokeSubject() in /_/Src/FluentAssertions/Specialized/FunctionAssertions.cs:line 26
     at FluentAssertions.Specialized.DelegateAssertions`2.InvokeSubjectWithInterception() in /_/Src/FluentAssertions/Specialized/DelegateAssertions.cs:line 221
.
   at FluentAssertions.Execution.LateBoundTestFramework.Throw(String message) in /_/Src/FluentAssertions/Execution/LateBoundTestFramework.cs:line 18
   at FluentAssertions.Execution.TestFrameworkProvider.Throw(String message) in /_/Src/FluentAssertions/Execution/TestFrameworkProvider.cs:line 34
   at FluentAssertions.Execution.DefaultAssertionStrategy.HandleFailure(String message) in /_/Src/FluentAssertions/Execution/DefaultAssertionStrategy.cs:line 25
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc) in /_/Src/FluentAssertions/Execution/AssertionScope.cs:line 274
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc) in /_/Src/FluentAssertions/Execution/AssertionScope.cs:line 246
   at FluentAssertions.Execution.AssertionScope.FailWith(String message, Object[] args) in /_/Src/FluentAssertions/Execution/AssertionScope.cs:line 296
   at FluentAssertions.Specialized.DelegateAssertionsBase`2.ThrowInternal[TException](Exception exception, String because, Object[] becauseArgs) in /_/Src/FluentAssertions/Specialized/DelegateAssertionsBase.cs:line 35
   at FluentAssertions.Specialized.DelegateAssertions`2.Throw[TException](String because, Object[] becauseArgs) in /_/Src/FluentAssertions/Specialized/DelegateAssertions.cs:line 48
   at UnitTests.FluentAssertionsEquivalencyFailureTest.NullReferenceFailure() in C:\Telgorithm\src\phone\tmp\My.UnitTests\FluentAssertionsFailureTest.cs:line 25
        */
    }
}

public class TestClass
{
    public DateTime? NullableField { get; set; }
}

Reproduction Steps

For reproduction please look at the description - there is a code sample which reproduces the error.

Expected behavior

Expected that the second test behaves exactly like the first.

Actual behavior

Unexpected NRE is thrown.

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Are you willing to help with a pull-request?

No

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions