Skip to content

Can't create substitute for delegate from some namespaces 🤯 #631

@kislovs

Description

@kislovs

Describe the bug
In short, I can't use Substitute.For<{delegate}>(); if this delegate from some namespaces. I discovered that namespaces started with N[a-s] led to exception, others work fine (I didn't tested any namespaces though). Also I found that it doesn't work for version 4.1.0 and later (I think it relates to #537), 4.0.0 works fine. Bug is permanently reproducable with 4.1.0+ version on different machines and operations systems. Though it works fine with Func<...> stuff.

To Reproduce

Test.csproj

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>

        <IsPackable>false</IsPackable>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="NSubstitute" Version="4.2.2" />
        <PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.13" />
        <PackageReference Include="NUnit" Version="3.12.0" />
        <PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
    </ItemGroup>
</Project>

Tests.cs

using NSubstitute;
using NUnit.Framework;

namespace Na { public delegate void DoNothing(); }
namespace Nb { public delegate void DoNothing(); }
namespace Nc { public delegate void DoNothing(); }
namespace Nd { public delegate void DoNothing(); }
namespace Ne { public delegate void DoNothing(); }
namespace Nf { public delegate void DoNothing(); }
namespace Ng { public delegate void DoNothing(); }
namespace Nh { public delegate void DoNothing(); }
namespace Ni { public delegate void DoNothing(); }
namespace Nj { public delegate void DoNothing(); }
namespace Nk { public delegate void DoNothing(); }
namespace Nl { public delegate void DoNothing(); }
namespace Nm { public delegate void DoNothing(); }
namespace Nn { public delegate void DoNothing(); }
namespace No { public delegate void DoNothing(); }
namespace Np { public delegate void DoNothing(); }
namespace Nq { public delegate void DoNothing(); }
namespace Nr { public delegate void DoNothing(); }
namespace Ns { public delegate void DoNothing(); }
namespace Nt { public delegate void DoNothing(); }
namespace Nu { public delegate void DoNothing(); }
namespace Nv { public delegate void DoNothing(); }
namespace Nw { public delegate void DoNothing(); }
namespace Nx { public delegate void DoNothing(); }
namespace Ny { public delegate void DoNothing(); }
namespace Nz { public delegate void DoNothing(); }

namespace Test
{
    public class Tests
    {
        [Test] public void Na() { Substitute.For<Na.DoNothing>(); }
        [Test] public void Nb() { Substitute.For<Nb.DoNothing>(); }
        [Test] public void Nc() { Substitute.For<Nc.DoNothing>(); }
        [Test] public void Nd() { Substitute.For<Nd.DoNothing>(); }
        [Test] public void Ne() { Substitute.For<Ne.DoNothing>(); }
        [Test] public void Nf() { Substitute.For<Nf.DoNothing>(); }
        [Test] public void Ng() { Substitute.For<Ng.DoNothing>(); }
        [Test] public void Nh() { Substitute.For<Nh.DoNothing>(); }
        [Test] public void Ni() { Substitute.For<Ni.DoNothing>(); }
        [Test] public void Nj() { Substitute.For<Nj.DoNothing>(); }
        [Test] public void Nk() { Substitute.For<Nk.DoNothing>(); }
        [Test] public void Nl() { Substitute.For<Nl.DoNothing>(); }
        [Test] public void Nm() { Substitute.For<Nm.DoNothing>(); }
        [Test] public void Nn() { Substitute.For<Nn.DoNothing>(); }
        [Test] public void No() { Substitute.For<No.DoNothing>(); }
        [Test] public void Np() { Substitute.For<Np.DoNothing>(); }
        [Test] public void Nq() { Substitute.For<Nq.DoNothing>(); }
        [Test] public void Nr() { Substitute.For<Nr.DoNothing>(); }
        [Test] public void Ns() { Substitute.For<Ns.DoNothing>(); }
        [Test] public void Nt() { Substitute.For<Nt.DoNothing>(); }
        [Test] public void Nu() { Substitute.For<Nu.DoNothing>(); }
        [Test] public void Nv() { Substitute.For<Nv.DoNothing>(); }
        [Test] public void Nw() { Substitute.For<Nw.DoNothing>(); }
        [Test] public void Nx() { Substitute.For<Nx.DoNothing>(); }
        [Test] public void Ny() { Substitute.For<Ny.DoNothing>(); }
        [Test] public void Nz() { Substitute.For<Nz.DoNothing>(); }
    }
}

It should results like that:
image

Full exception stacktrace:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: System.Object.
Could not find a parameterless constructor.
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.CreateProxyUsingCastleProxyGenerator(Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments, IInterceptor[] interceptors, ProxyGenerationOptions proxyGenerationOptions)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.GenerateDelegateProxy(ICallRouter callRouter, Type delegateType, Type[] additionalInterfaces, Object[] constructorArguments)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.GenerateProxy(ICallRouter callRouter, Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments)
   at NSubstitute.Core.SubstituteFactory.Create(Type[] typesToProxy, Object[] constructorArguments, Boolean callBaseByDefault)
   at NSubstitute.Core.SubstituteFactory.Create(Type[] typesToProxy, Object[] constructorArguments)
   at NSubstitute.Substitute.For(Type[] typesToProxy, Object[] constructorArguments)
   at NSubstitute.Substitute.For[T](Object[] constructorArguments)
   at Test.Tests.Na()

Expected behaviour
Substitute should be created without any problems.

Environment:

  • NSubstitute version: 4.1.0 and later
  • NSubstitute.Analyzers version: CSharp 1.0.13
  • Platform: netcoreapp3.1, Windows / Linux

Additional context
I have no idea why it doen't works... It sounds mind-blowing if something doesn't work because of namespace 🤯

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugReported problem with NSubstitute behaviour

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions