Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Mocking non-virtual methods of a class

Posted on 4 October 2020

Introduction

Usually I use interfaces for my unit tests. This is a good practice, and should be followed when possible. But, last week I was testing some legacy code, which had no interfaces and stumbled with something: I was trying to mock a class with a non-virtual method and saw that the original method was being executed, instead of doing nothing (the expected for the mock). I was using NSubstitute, but the same principles apply to most of the more popular mocking frameworks, like Moq, FakeItEasy or Rhino mocks. All of them use for their backend Castle DynamicProxy to create a proxy around the object and do its magic. All of them state that they can only mock virtual methods, so I should be aware that I could not mock non-virtual methods.

This would be ok if the class to be mocked is yours, just add the Virtual keyword to your method and you're done. You'll have some size and performance penalty in exchange for your flexibility. Or you could use something like Typemock Isolator (this is a great mocking framework that can mock almost anything)- that would work even if you don't have access to the source code. But why aren't non-virtual methods mocked ?

Let's start with an example. Let's say I have the code of the class below:

public class ClassNonVirtualMehods
{
    public void NonVirtualMethod()
    {
         Console.WriteLine("Executing Non Virtual Method");
    }

    public virtual void VirtualMethod()
    {
        Console.WriteLine("Executing Virtual Method");
    }
}
C#

My class to test receives an instance of this class:

public class ClassToTest
{
    public void CallVirtualMethod(ClassNonVirtualMehods param)
    {
        param.VirtualMethod(); 
    }

    public void CallNonVirtualMethod(ClassNonVirtualMehods param)
    {
        param.NonVirtualMethod();
    }
}
C#

My tests are (I'm using NSubstitute here):

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestVirtualMethod()
    {
        var mock = Substitute.For<ClassNonVirtualMehods>();
        var sut = new ClassToTest();
        sut.CallVirtualMethod(mock);
    }

    [TestMethod]
    public void TestNonVirtualMethod()
    {
        var mock = Substitute.For<ClassNonVirtualMehods>();
        var sut = new ClassToTest();
        sut.CallNonVirtualMethod(mock);
    }
}
C#

If you run these tests, you'll see this:

You'll see that the non virtual method is executed (writing to the console), while the virtual method is not executed, as we expected.

Why aren't non-virtual methods mocked ?

To explain that, we should see how Castle DynamicProxy works and how C# polymorphism works.

From here, you can see that DynamicProxy works with two types of proxies: Inheritance-based and composition-based. In order to put in place their mocks, the mock frameworks use the inheritance-based proxy, and that would be the same as create an inherited class (the mock) that overrides the methods and put the desired behavior in them. It would be something like this:

public class MockClassWithNonVirtualMethods : ClassNonVirtualMehods
{
    public override void VirtualMethod()
    {
        // Don't do anything
    }
}
C#

In this case, as you can see, you can only override virtual methods, so the non-virtual methods will continue to execute the same way. If you have tests like this ones, you will see the same behavior as you did with NSubstitute:

You could use the composition-based proxy, but when you read the documentation, you'll see that this is not an option:

Class proxy with target - this proxy kind targets classes. It is not a perfect proxy and if the class has non-virtual methods or public fields these can't be intercepted giving users of the proxy inconsistent view of the state of the object. Because of that, it should be used with caution.

Workaround for non-virtual methods

Now we know why mocking frameworks don't mock non-virtual methods, we must find a workaround.

My first option was to use the RealProxy class to create the mock and intercept the calls, like shown in my article in the MSDN Magazine. This is a nice and elegant solution, as the impact to the source code would be minimum, just create a generic class to create the proxy and use it instead of the real class. But it turned on that the RealProxy has two disadvantages:

  • It can only create proxies that inherit of MarshalByRefObjector are interfaces, and our classes are none of them
  • It isn't available in .NET Core, and it was replaced by DispatchProxy, which is different, and can only proxy interfaces

So, I discarded this option and went for another option. I was looking to change the IL Code at runtime, usingReflection.Emit, but this is prone to errors and not an easy task, so I kept searching until I found Fody. This is a very interesting framework to allow you to add new code at runtime. This is the same thing I was expecting to do, with the difference that the solutions are ready and tested. Just add an add-in and you're set - the task you are trying to do is there. There are a lot of add-ins for it and it's very simple to use them. If you don't find what you are trying to do there, you can develop your own add-in. In our case, there is already an add-in, Virtuosity.

To use it, all we have to do is to install the packages Fody and Fody.Virtuosity to your project, add a xml file named FodyWeavers.xml with this content:

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Virtuosity />
</Weavers>
XML

Set its Build Action to None and Copy to Output Directory to Copy If Newer and you're set. This will transform all your non-virtual methods to virtual and you will be able to mock them in any mocking framework, with no need to change anything else in your projects.

Conclusion

The procedure described here is nothing something that I would recommend doing on a daily basis, but when you have some legacy code to test, where changes to the source code are difficult to make, it can be a lifesaver. When you have the time and the means, you should develop an interface and use it in your code, using Dependency Injection. That way, you will reduce coupling and enhance its maintainability.

All the source code for this article is at https://github.com/bsonnino/MockNonVirtual

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About