tonerdo / pose

Replace any .NET method (including static and non-virtual) with a delegate
MIT License
1.07k stars 75 forks source link

When shimming DateTimeOffset access to the `.Date` property throws "Object reference not set to an instance of an object" #81

Open douglasg14b opened 1 week ago

douglasg14b commented 1 week ago

It seems that something is messed up here.

Using Poser v2.1.0


        Shim dateTimeShim = Shim.Replace(() => DateTimeOffset.UtcNow)
            .With(() => DateTimeOffset.Parse(startDate, styles: DateTimeStyles.AssumeUniversal).AddMonths(monthIndex));

        PoseContext.Isolate(() =>
            {
                bool test2 = DateTimeOffset.UtcNow.Date > DateTimeOffset.UtcNow.AddMonths(1).Date;
            },
            dateTimeShim);
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at impl_System.DateTimeOffset_AddMonths(DateTimeOffset&, Int32)
   at stub_call_System.DateTimeOffset_AddMonths(DateTimeOffset&, Int32)
   at impl_Buzzscreens.Features.Tests.Orders.OrderTests+<>c_<WithOrder_NextBillingDate_ReturnsCorrectDate>b__1_4(<>c)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at Pose.PoseContext.Isolate(Action entryPoint, Shim[] shims)
   at Buzzscreens.Features.Tests.Orders.OrderTests.WithOrder_NextBillingDate_ReturnsCorrectDate(String startDate, String endDate, Int32 monthIndex, String expectedEnd, Boolean shouldEndBeLastMonth) in C:\Users\Douglas\Documents\01 Programming\02 Contracts\buzzscreens-app\apps\backend\Buzzscreens.Features.Tests\Orders\OrderTests.cs:line 60
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithManyArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

The following works as expected:

        DateTime test = DateTimeOffset
            .Parse(startDate, styles: DateTimeStyles.AssumeUniversal)
            .AddMonths(monthIndex)
            .Date;
douglasg14b commented 1 week ago

Similar thing happens with the example DateTime shim:

        Shim dateTimeShim = Shim.Replace(() => DateTime.UtcNow)
            .With(() => new DateTime(2004, 4, 4));

DateTimeOffset.UtcNow.AddMonths(1); throws something similar:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at impl_System.DateTimeOffset_AddMonths(DateTimeOffset&, Int32)
   at stub_call_System.DateTimeOffset_AddMonths(DateTimeOffset&, Int32)
   at impl_Buzzscreens.Features.Tests.Orders.OrderTests+<>c_<WithOrder_NextBillingDate_ReturnsCorrectDate>b__1_4(<>c)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)