Search code examples
c#unit-testingfluent-assertions

FluentAssertions WhenTypeIs double.NaN


I have two complex objects, with diferent types inside(objects, strings, doubles, etc). I want to compare them by using the following code:

myActualObject.ShouldBeEquivalentTo(myExpectedObject, options => options
        .Using<double>(dbl => dbl.Subject.Should().BeApproximately(dbl.Expectation,
         ABS_ERROR))
        .WhenTypeIs<double>()
    );

I am trying to compare the double type property values using the .BeApproximately behaviour, but does not work correctly because of one special case:

  • Sometimes I have a double.NaN inside the double, and comparing a NaN with another NaN gives an assertion fail(because of the BeApproximately behaviour). How can I skip the comparison, or make it true in this case?

  • And lastly, how can I print the name of the object that caused the assertion fail?

Thanks in advance.

EDIT >>>>

I've found a first approach(thanks to @Sam Holder):

myActualObject.ShouldBeEquivalentTo(myExpectedObject, options => options
        .Using<double>(ctx => CompareDoubleApprox(ctx, myExpectedObject.Name))
        .WhenTypeIs<double>()
);

...

public void CompareDoubleApprox(IAssertionContext<double> ctx, string Scope)
{
    bool IsDoubleOrInfinite = (double.IsNaN(ctx.Expectation) || double.IsInfinity(ctx.Expectation));
    bool absoluteErrorOK = Math.Abs(ctx.Subject - ctx.Expectation) < ABS_ERROR;

    Execute.Assertion
         .BecauseOf(ctx.Reason, ctx.ReasonArgs)
         .ForCondition(IsDoubleOrInfinite || absoluteErrorOK)
         .FailWith("{3}: Expected {context:double} to be {0} +/- {1} {reason}, but found {2}", ctx.Subject, ABS_ERROR, ctx.Expectation, Scope);
}

My assert dump looks like:

"MyObjectName": Expected member Foo.Bar to be 0 +/- 1E-05 , but found 1,39675

"MyObjectName": Expected member Foo.FooBar to be 2,07781 +/- 1E-05 , but found 2,98412

...More assertion fails...

And I want it to print the objectName just one time, before printing all the fails.

UPDATE>>>>

The behaviour I want is not implemented yet on github: https://github.com/dennisdoomen/fluentassertions/issues/310. Is marked as a enhancement. Thanks for your help.


Solution

  • Untested stab in the dark, but might something like this work:

    myActualObject.ShouldBeEquivalentTo(myExpectedObject, options => options
        .Using<double>(dbl =>
           { 
               if (!double.IsNaN(dbl.Subject))
               {
                   String errorMessage = string.Format("{0} caused the assertion to fail",myExpectedObject);
                   dbl.Subject.Should().BeApproximately(dbl.Expectation, ABS_ERROR, errorMessage);
               }
           })
        .WhenTypeIs<double>()
    );