Skip to content

Cannot mock subclass of superclass with internal virtual methods #991

@GeeWee

Description

@GeeWee

Unfortunately, this bug report is a little confusing, as I have tried multiple times to create a small reproducible example, but I am unable to.

I'm trying to make a mock of the Azure BlockBlobClient
This works fine, I can easily execute

var clientMock = new Mock<BlockBlobClient>();
var obj = clientMock.Object;

However, if I subclass the BlockBlobClient, everything goes wrong, even if the subclass does nothing.

[Fact]
public void ShouldBeAbleToSubclass()
{
    // Arrange
    var clientMock = new Mock<TestBlockBlobClient>();
    var obj = clientMock.Object;
}

}

public class TestBlockBlobClient : BlockBlobClient
{
}

I then get the following error:

  Error Message:
   System.ArgumentException : Type to mock must be an interface, a delegate, or a non-sealed, non-static class.
---- System.TypeLoadException : Method 'get_Pipeline' on type 'Castle.Proxies.TestBlockBlobClientProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is overriding a method that is not visible from that assembly.
  Stack Trace:
     at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments)
   at Moq.Mock`1.InitializeInstance()
   at Moq.Mock`1.OnGetObject()
   at Moq.Mock.get_Object()
   at Moq.Mock`1.get_Object()
   at AIP.Shared.Test.BlockBlobClientTests.ShouldBeAbleToSubclass() in /home/geewee/programming/OAI/Shared.Test/BlockBlobClientTests.cs:line 91
----- Inner Stack Trace -----
   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType(TypeBuilder type)
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
   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__DisplayClass33_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.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
   at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments)

It seems like Moq is trying to mock the internal virtual method Pipeline in the BlobBaseClient, which the BlockBlobClient inherits from.

Seeing as the method is internal and in another assembly, I cannot override it. However if I define a property with the same name, ala:

public class TestBlockBlobClient : BlockBlobClient
{
    public HttpPipeline Pipeline => null!;
}

I get the same error, but with the next internal virtual property

 System.TypeLoadException : Method 'get_Version' on type 'Castle.Proxies.TestBlockBlobClientProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is overriding a method that is not visible from that assembly.

which is also a property on the superclass

So my theory is that there's something that's going on with the internal virtual properties, but only in a subclass of a subclass in another assembly.

Unfortunately, I cannot reproduce the problem, if I try to mimick the same thing locally (e.g. create two assemblies and the same internal virtual structure). I'm not sure if this is a Windsor or a Moq problem either.

Back this issue
Back this issue

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions