-
Notifications
You must be signed in to change notification settings - Fork 485
Closed
Description
Describe the bug
Castle proxy fails to create a substitute for a concrete class that derives from an abstract class and virtual members.
To Reproduce
Here's an example of what I am talking about:
Setup classes
namespace TestNSubstituteBS
{
public abstract class AbstractIOContext
{
public abstract IDirectoryInfo CreateDirectoryInfo();
}
}namespace TestNSubstituteBS
{
public class ConcreteIOContext : AbstractIOContext
{
public override XDirectoryInfo CreateDirectoryInfo() => new XDirectoryInfo();
}
}namespace TestNSubstituteBS
{
public class XDirectoryInfo : IDirectoryInfo { }
}namespace TestNSubstituteBS
{
public interface IDirectoryInfo { }
}Test code:
namespace TestNSubstituteBS.Tests
{
[TestClass()]
public class AbstractFactoryTests
{
[TestMethod]
public void CreateTest()
{
var a = Substitute.For<ConcreteIOContext>(); // <--------------- fails here
a.CreateDirectoryInfo().Returns(new XDirectoryInfo());
}
}
}Running the above returns this error message...
Test method TestNSubstituteBS.Tests.AbstractFactoryTests.CreateTest threw exception:
System.TypeLoadException: Return type in method 'Castle.Proxies.ConcreteIOContextProxy.CreateDirectoryInfo()' on type 'Castle.Proxies.ConcreteIOContextProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with base type method 'TestNSubstituteBS.ConcreteIOContext.CreateDirectoryInfo()'.and stack trace...
Stack Trace:
TypeBuilder.CreateTypeNoLock()
TypeBuilder.CreateTypeInfo()
AbstractTypeEmitter.BuildType()
BaseClassProxyGenerator.GenerateType(String name, INamingScope namingScope)
<>c__DisplayClass13_0.<GetProxyType>b__0(CacheKey cacheKey)
SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
BaseProxyGenerator.GetProxyType()
DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
CastleDynamicProxyFactory.CreateProxyUsingCastleProxyGenerator(Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments, IInterceptor[] interceptors, ProxyGenerationOptions proxyGenerationOptions)
CastleDynamicProxyFactory.GenerateTypeProxy(ICallRouter callRouter, Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments)
CastleDynamicProxyFactory.GenerateProxy(ICallRouter callRouter, Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments)
SubstituteFactory.Create(Type[] typesToProxy, Object[] constructorArguments, Boolean callBaseByDefault)
SubstituteFactory.Create(Type[] typesToProxy, Object[] constructorArguments)
Substitute.For(Type[] typesToProxy, Object[] constructorArguments)
Substitute.For[T](Object[] constructorArguments)
AbstractFactoryTests.CreateTest() line 18As it turns out, it seems that there is an issue with the proxy when the ConcreteIOContext has the return type XDirectoryInfo, which does implement IDirectoryInfo, but not stated explicitly. If stated explicitly, the issue goes away.
namespace TestNSubstituteBS
{
public class ConcreteIOContext : AbstractIOContext
{
// public override XDirectoryInfo CreateDirectoryInfo() => new XDirectoryInfo(); <-- does not work
public override IDirectoryInfo CreateDirectoryInfo() => new XDirectoryInfo(); // <--- this does work
}
}The code above now makes it work without any issue.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels