Skip to content

Trying to configure/override a generic overridden virtual method with an out parameter on a class substitute throws an exception #716

@rbeurskens

Description

@rbeurskens

Describe the bug
Trying to configure/override a generic overridden virtual method with an out parameter on a class substitute throws an exception.

System.ArgumentException : Could not find method overriding Boolean TryCreateControl[TResult](IBaseControl, IHasGridLinesDefined, TResult ByRef) on type MyControlFactory. This is most likely a bug. Please report it.
   at Castle.DynamicProxy.Internal.InvocationHelper.ObtainMethod(MethodInfo proxiedMethod, Type type)
   at Castle.Core.Internal.SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Castle.DynamicProxy.Internal.InvocationHelper.GetMethodOnType(Type type, MethodInfo proxiedMethod)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleInvocationMapper.Map(IInvocation castleInvocation)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleForwardingInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.MyControlFactoryProxy.TryCreateControl[TResult](IBaseControl control, IHasGridLinesDefined parentGrid, TResult& result)

To Reproduce

given:

public interface IControlFactory
{
    bool TryCreateControl<TResult>(IBaseControl control, IHasGridLinesDefined? parentGrid, [MaybeNullWhen(false)] out TResult result);
}
public class ControlFactory: IControlFactory
{
    public virtual bool TryCreateControl<TResult>(IBaseControl control, IHasGridLinesDefined? parentGrid, [MaybeNullWhen(false)] out TResult result) { /* ... */ }
}
public class MyControlFactory: ControlFactory
{
    // If this override is removed, code runs as expected
    public override bool TryCreateControl<TResult>(IBaseControl control, IHasGridLinesDefined? parentGrid, [MaybeNullWhen(false)] out TResult result) { /* ... */ }
}

[Test]
void MyTest()
{
    var control = Substitute.For<IStringTextBoxControl>();
    var controlFactory = Substitute.For<MyControlFactory>();
    controlFactory.Configure().TryCreateControl<object>(default, default, out var _)
          .ReturnsForAnyArgs(ci => { ci[2] = control; return true; }); // <== exception here
}

Expected behaviour
Runs normally and the method returns the desired object when called

Environment:

  • NSubstitute version: 5.0.0
  • NSubstitute.Analyzers version: CSharp 1.0.16
  • Platform: .NET Framework 4.8

Additional context
This might be a bug in Castle.Core or wrong usage of it, but I can't tell.
If the method override in the MyControlFactory class is removed, the exception does not occur and code runs as expected

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedCore team needs help with this! If you've got some time, please volunteer to take a look.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions