Castle.DynamicProxy.ProxyGenerationException when creating mock.
When creating mock using Substitute.For method got exception : Castle.DynamicProxy.ProxyGenerationException: Duplicate element: Castle.DynamicProxy.Generators.MetaMethod.
To Reproduce Create two identical interfaces with one identical method in two namespaces. Inherit one of the interfaces and define the same method. sample setup:
namespace firstNamespace
{
public interface BaseObject1
{
string SomeMethod { get; }
}
}
namespace SecondNamespace
{
public interface BaseObject1
{
string SomeMethod { get; }
}
public interface BaseFolder1 : BaseObject1
{
string SomeMethod { get; }
}
}
Try create mock using Substitute.For method like that:
firstNamespace.BaseObject1 mock = Substitute.For<firstNamespace.BaseObject1, SecondNamespace.BaseFolder1>();
At first attempt please use exactly the same name for namespaces and interfaces. Even small change eg. FirstNamespace instead of firstNamespace magically fixes this issue.
Expected behaviour Allow creating mock for provided scenario.
Environment:
- NSubstitute version: 4.2.1.0
- NSubstitute.Analyzers version: unable to successfully install
- Platform: windows 8.1, Visual Studio Express Edition 2015 version 14.0.25123.00 update 2, Net Framework version 4.8.03761
Additional context Sample VS project reproducing the issue is attached here: NSubstituteIssue.zip
Stack trace from exception:
at Castle.DynamicProxy.Generators.TypeElementCollection`1.Add(TElement item)
at Castle.DynamicProxy.Contributors.CompositeTypeContributor.CollectElementsToProxy(IProxyGenerationHook hook, MetaType model)
at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope)
at Castle.DynamicProxy.Generators.ClassProxyGenerator.<>c__DisplayClass1_0.<GenerateCode>b__0(String n, INamingScope s)
at Castle.DynamicProxy.Generators.BaseProxyGenerator.<>c__DisplayClass34_0.<ObtainProxyType>b__0(CacheKey _)
at Castle.Core.Internal.SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
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.GenerateTypeProxy(ICallRouter callRouter, Type typeToProxy, 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[T1,T2](Object[] constructorArguments)
at NSubstituteIssue.UnitTest1.TestMethod1() in C:\NSubstituteIssue\NSubstituteIssue\UnitTest1.cs:line 35
Thanks for the brilliantly crafted scenario!
@stakx Hey! If you have time these days, could you please take a look? It looks like a pure Castle issue, as we pass interfaces just as is (like Moq I believe).
If you don’t have time - it’s totally OK, we could also investigate it ourselves.
Thanks!
@zvirja, thanks for the ping, I'll take a look and report what I find.
We've fixed the root cause for this problem in DynamicProxy. Thank you all for bringing this to our attention!
NSubstitute.Analyzers version: unable to successfully install
@compact-github could you tell what was wrong when you tried to install NSubstitute.Analyzers?
Sure. Using Nuget Package manager I installed NSubstitute.Analyzers.CSharp package in version 1.0.10. After that, when compiling project I got:
CSC : warning CS8032: An instance of analyzer NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers.NonSubstitutableMemberWhenAnalyzer cannot be created from C:\NSubstituteIssue\packages\NSubstitute.Analyzers.CSharp.1.0.10\analyzers\dotnet\cs\NSubstitute.Analyzers.CSharp.dll : Could not load file or assembly 'Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified..
So I installed Microsoft.CodeAnalysis package in version 1.3.1. This installed also 18 additional packages. I got exactly the same warn as previous, preceded by:
C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): warning MSB3274: The primary reference "Microsoft.CodeAnalysis.Workspaces.Desktop, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" could not be resolved because it was built against the ".NETFramework,Version=v4.5.2" framework. This is a higher version than the currently targeted framework ".NETFramework,Version=v4.5".
I tried update Microsoft.CodeAnalysis to most recent version 3.2.1. Nothing changed, so I updated rest of the packages installed with Microsoft.CodeAnalyzers. Still no success and I gave up. I'm not familiar with the analyzer stuff. Maybe problem is related to my old Visual Studio Express edition.
Sorry for the delayed answer, but during weekend I was out of internet.
@compact-github you most likely use Visual Studio version which is not compatible with the analyzers. Can you check if your Visual Studio falls into supported version range listed in docs?
@tpodolak Yes, you are right. Visual Studio 2015 Express is not supported. Even Visual Studio 2015 is not supported. For me is not a problem. For noncommercial activity I can download more recent community version. In the company we have few full version Visual Studio licenses. I'm not full time c# developer so currently I don't have any and use old express version.