Build/Test Issues

RDI causes Exception with NSubstitute

Started by JulienN on 3,185 views

We have a series of tests that uses NSubstitute to override some properties in an Exception in order to test one of our extension method.

This code works properly without RDI enabled, but fails with an exception when RDI is enabled (NCrunch v5.3.0.2)

 var exception  = Substitute.For<Exception>();
 var stackTrace = "...");
 //...
 exception.StackTrace.Returns(stackTrace);
 exception.GetBaseException().Returns(exception);


Exception is :
NSubstitute.Exceptions.CouldNotSetReturnDueToTypeMismatchException : Can not return value of type ExceptionProxy for Exception.get_StackTrace (expected type String).

Make sure you called Returns() after calling your substitute (for example: mySub.SomeMethod().Returns(value)),
and that you are not configuring other substitutes within Returns() (for example, avoid this: mySub.SomeMethod().Returns(ConfigOtherSub())).

(+more a lot of suggestions on how to use NSubstitute)

Edited

Hi, thanks for sharing this issue.

Are you able to build a full code sample that can reproduce this problem? I've tried using the short example you've given me, but I can't seem to make it happen.

My theory is that the RDI instrumentation is somehow interfering with NSubstitue. There were some issues with this early in development, though I thought we had it all nailed down. I guess there must be a case that we're not handling right in here.

It should be possible to work around this issue by using RDI inline directives to switch off RDI in these code blocks, but I'd like to see if there's a way we can handle this out of the box.
Hello,

I'll see if I can find the time to create a project from scratch.

Until then, here a the full, buildable test file :

using NSubstitute;

namespace Namespace;

public class ExtensionsTest
{
    [Test]
    public void Test()
    {
        var exception  = Substitute.For<Exception>();

        exception.GetBaseException().Returns(exception);  //<--- Exception here

        Assert.That(exception.GetBaseException(), Is.EqualTo(exception));
    }
}


The full stacktrace :
NSubstitute.Exceptions.CouldNotSetReturnDueToTypeMismatchException : Can not return value of type ExceptionProxy for Exception.get_StackTrace (expected type String).

Make sure you called Returns() after calling your substitute (for example: mySub.SomeMethod().Returns(value)),
and that you are not configuring other substitutes within Returns() (for example, avoid this: mySub.SomeMethod().Returns(ConfigOtherSub())).

If you substituted for a class rather than an interface, check that the call to your substitute was on a virtual/abstract member.
Return values cannot be configured for non-virtual/non-abstract members.

Correct use:
mySub.SomeMethod().Returns(returnValue);

Potentially problematic use:
mySub.SomeMethod().Returns(ConfigOtherSub());
Instead try:
var returnValue = ConfigOtherSub();
mySub.SomeMethod().Returns(returnValue);

at NSubstitute.Core.ConfigureCall.CheckResultIsCompatibleWithCall(IReturn valueToReturn, ICallSpecification spec)
at NSubstitute.Core.ConfigureCall.SetResultForLastCall(IReturn valueToReturn, MatchArgs matchArgs, PendingSpecificationInfo pendingSpecInfo)
at NSubstitute.Core.CallRouter.LastCallShouldReturn(IReturn returnValue, MatchArgs matchArgs, PendingSpecificationInfo pendingSpecInfo)
at NSubstitute.Core.ThreadLocalContext.LastCallShouldReturn(IReturn value, MatchArgs matchArgs)
at NSubstitute.SubstituteExtensions.ConfigureReturn[T](MatchArgs matchArgs, T returnThis, T[] returnThese)
at NSubstitute.SubstituteExtensions.Returns[T](T value, T returnThis, T[] returnThese)
at Namespace.ExtensionsTest.Test() in ExtensionsTest.cs:line 12
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)



Note that we are not using StackTrace, though the exception is mentioning it.
I tried disabling/enabling RDI, restarting the VS, it is always the same exception on get_StackTrace

Context is :
* .NET 8.0
* Visual Studio 2022 17.9.2
* NCrunch 5.3.0.2
* NUnit 4.0.1
* NSubstitute 5.1.0
* Microsoft.NET.Test.Sdk 17.8.0






Strangely, this code seems to work fine for me when I build a sample identical to what you've described. There must be a component I'm missing here. Please do let me know if you manage to set up a self contained solution that can produce this. You can submit small code samples through the NCrunch contact form.
This post has been deleted.
This post has been deleted.

Post a reply

Log in to reply.