Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MissingMethodException when mocking interface with sealed default implementation #1209

Closed
pjquirk opened this issue Sep 15, 2021 · 2 comments · Fixed by #1277
Closed

MissingMethodException when mocking interface with sealed default implementation #1209

pjquirk opened this issue Sep 15, 2021 · 2 comments · Fixed by #1277
Assignees
Milestone

Comments

@pjquirk
Copy link

pjquirk commented Sep 15, 2021

I thought this might fall under the #1148 umbrella, but using the latest 6.0 release (6.0.100-rc.1.21458.32) still results in the error.

I think the expected behavior here should be to use the default implementation if CallBase is true, otherwise, error as cannot be mocked. This repro errors regardless of the value of CallBase.

Repro

using Moq;

namespace moqrepro
{
    class Program
    {
        static void Main(string[] args)
        {
            var mock = new Mock<ILog>();

            // This setup has no effect
            // mock.Setup(p => p.Log(It.IsAny<string>()))
            //     .Callback<string>(msg => Console.WriteLine(msg));

            // XXX: This throws
            mock.Object.Log();
        }
    }

    public interface ILog
    {
        // Remove sealed to avoid exception above
        public sealed void Log()
        {
            Log("Testing");
        }

        void Log(string msg);
    }
}

Full build/run log:

> dotnet restore

Welcome to .NET 6.0!
---------------------
SDK Version: 6.0.100-rc.1.21458.32

Telemetry
---------
The .NET tools collect usage data in order to help us improve your experience. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate run 'dotnet dev-certs https --trust' (Windows and macOS only).
Learn about HTTPS: https://aka.ms/dotnet-https
----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
  Determining projects to restore...
  Restored /Users/pjquirk/Source/scratch/moqrepro/moqrepro.csproj (in 338 ms).

> dotnet build
Microsoft (R) Build Engine version 17.0.0-preview-21458-01+2c5510013 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
  moqrepro -> /Users/pjquirk/Source/scratch/moqrepro/bin/Debug/net6.0/moqrepro.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.15

> dotnet run
Unhandled exception. System.MissingMethodException: Method not found: 'Void moqrepro.ILog.Log()'.
   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.InterfaceProxyWithoutTargetGenerator.GenerateType(String typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.<>c__DisplayClass6_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.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
   at Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
   at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments) in C:\projects\moq4\src\Moq\ProxyFactories\CastleProxyFactory.cs:line 50
   at Moq.Mock`1.InitializeInstance() in C:\projects\moq4\src\Moq\Mock`1.cs:line 311
   at Moq.Mock`1.OnGetObject() in C:\projects\moq4\src\Moq\Mock`1.cs:line 325
   at Moq.Mock.get_Object() in C:\projects\moq4\src\Moq\Mock.cs:line 179
   at Moq.Mock`1.get_Object() in C:\projects\moq4\src\Moq\Mock`1.cs:line 283
   at moqrepro.Program.Main(String[] args) in /Users/pjquirk/Source/scratch/moqrepro/Program.cs:line 15

I'm on MacOS Catalina 10.15.7 (19H1323).

@wzchua
Copy link

wzchua commented Oct 25, 2021

DynamicProxy fails to check that the method is not virtual here

@stakx stakx added this to the 4.18.2 milestone Aug 2, 2022
@stakx stakx self-assigned this Aug 2, 2022
@stakx stakx changed the title MissingMethodException when mocking interface with sealed default implementations MissingMethodException when mocking interface with sealed default implementation Aug 2, 2022
@stakx
Copy link
Contributor

stakx commented Aug 2, 2022

@pjquirk, I'm just about to release Moq version 4.18.2 to NuGet, which includes a fix for this. Thanks again for reporting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants