-
Notifications
You must be signed in to change notification settings - Fork 731
Description
Currently WhenTypeIs checks the runtime type of the expectation.
This can cause a NullReferenceException in CreateFromEquivalencyValidationContext in the following example.
var obj1 = new { date = (DateTime?)null };
var obj2 = new { date = (DateTime?)default(DateTime) };
var actual = new[] { obj1, obj2 };
var expected = new[] { obj2, obj1 };
actual.Should().BeEquivalentTo(expected, options => options
.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation, 1.Seconds()))
.WhenTypeIs<DateTime>());As the runtime type of default(DateTime) is DateTime, WhenTypeIs will match.
CreateFromEquivalencyValidationContext will then cast the null subject to a DateTime causing a NullReferenceException.
Another case is when a struct implements an interface, and CreateFromEquivalencyValidationContext cast a null into the struct type.
I propose that we change the logic of WhenTypeIs to consider whether the RuntimeType or CompileTimeType is a value type.
I have implemented the proposal here.
It is not a compile-breaking change, but if you relied on WhenTypeIs<DateTime> to match DateTime? it will break your code.
As there aren't that many tests of WhenTypeIs I wanted to start a discussion on the intended/expected behavior before submitting a PR:
This was inspired by the problem presented in #778 .