Mocking Static Methods for Unit Testing

As you probably know, unit tests are supposed to be fast, lightweight tests of your code logic. They are not supposed to do any disk I/O, network communication, or long-running CPU calculations. If you have cleanly decoupled code that doesn’t call any static methods and everything is programmed to the interface, you can mock the intensive operations very easily.
Although if you’ve tried unit testing a class that calls static methods that perform such intensive operations, you quickly realize that you must separate them out from your code so that they can be mocked.  But if the methods are in a library you can’t modify, you usually end up very frustrated. There are a few easy ways to mock static methods, and you can choose which option works best for your needs.

Background

In our example, we have a class that has a single static method. Let’s pretend that this does some intensive activity that you don’t want to do while running your unit test suite. This class is in a library that you can’t modify and make non-static – we’re just looking at the code here as an example.
namespace SomeLibraryYouCantModify
{
    public static class SomeStaticClass
    {
        public static bool SomeStaticMethod(string input)
        {
            // Let's pretend this method hits a database or service.
            return !string.IsNullOrEmpty(input);
        }
    }
}


So we have one method that takes a string and returns bool. Keep this in mind.


Now, here’s an example of the static method being used. Note that we can not (by default) mock the static call – it’s a tight coupling that can not be easily broken.


namespace SomeLibraryYouCanModify
{
    public class SomeUntestableClass
    {
        public int SomeMethod(string input)
        {
            var value = SomeStaticClass.SomeStaticMethod(input);

            return value ? 1 : 0;
        }
    }
}



Below you will find a variety of options to make this class unit testable without the static call.





Option 1 – Wrapper Class



The first option which is extremely easy to do and very Inversion-of-Control-friendly is to make a wrapper class that has the exact same signature as the static methods you’re needing to call, but the only difference is that they are non-static. Each of these methods calls the static version and returns the value (if not void). Then, you can extract an interface to use for wiring up with IoC and mocking (such as with Moq).


In this example, we take the same signature as our static class above, but create a non-static wrapper class.


namespace SomeLibraryYouCanModify
{
    public class StaticWrapper : IStaticWrapper
    {
        public bool SomeStaticMethod(string input)
        {
            return SomeStaticClass.SomeStaticMethod(input);
        }
    }
}


With our static wrapper in place, we now extract an interface:


namespace SomeLibraryYouCanModify
{
    public interface IStaticWrapper
    {
        bool SomeStaticMethod(string input);
    }
}


Perfect. Now we have a non-static wrapper class to our static methods that can be mocked. Here’s how to use it in the caller class:


namespace SomeLibraryYouCanModify
{
    public class WrapperMethod
    {
        IStaticWrapper _wrapper;

        public WrapperMethod(IStaticWrapper wrapper)
        {
            _wrapper = wrapper;
        }

        public int SomeMethod(string input)
        {
            var value = _wrapper.SomeStaticMethod(input);

            return value ? 1 : 0;
        }
    }
}


This class uses constructor injection, but you can do any Inversion-of-Control style you prefer (property injection, etc.). The main point is that we now have a hook where we can insert a mocked wrapper that does not call the static method. Here’s how our test class might look:


    [TestClass]
    public class WrapperMethodTests
    {
        private class TestWrapper : IStaticWrapper
        {
            public bool SomeStaticMethod(string input)
            {
                return !string.IsNullOrEmpty(input);
            }
        }

        [TestMethod]
        public void SomeMethod_GivenNull_ShouldReturnZero()
        {
            var wrapper = new TestWrapper();

            var wm = new WrapperMethod(wrapper);

            var output = wm.SomeMethod(null);

            Assert.AreEqual(0, output);
        }
    }


Notice how the TestWrapper is a private class just used for unit testing, and it does not do any time or I/O intensive operations. This allows our unit tests to execute quickly, providing quick turn-around when things break.


You could also use a mocking framework like Moq to create a mocked IStaticWrapper in the test example above.




Option 2 – Delegates



If the amount of static operations you’re trying to mock is small, say one or two method calls, you may want to go the delegate route. In this approach, you take optional delegates into the constructor so that by default the class calls the static method, but in your unit tests you can specify a custom delegate (such as a lambda method) that is called instead.


Here’s our caller class using the delegate method:


namespace SomeLibraryYouCanModify
{
    public class DelegateMethod
    {
        Func<string, bool> _delegate;

        public DelegateMethod()
        {
            _delegate = SomeStaticClass.SomeStaticMethod;
        }

        public DelegateMethod(Func<string, bool> method)
        {
            _delegate = method;
        }

        public int SomeMethod(string input)
        {
            var value = _delegate(input);

            return value ? 1 : 0;
        }
    }
}



If you aren’t familiar with generic delegates, Func<T, TResult> used above is a delegate for a method that takes a parameter of type T and returns a result of type TResult. So now our class, by default, sets the private delegate field to the static method, but in our unit tests we can specify a custom method instead. Here’s a unit test using this approach that passes a lambda into the constructor:


    [TestClass]
    public class DelegateMethodTests
    {
        [TestMethod]
        public void SomeMethod_GivenNull_ShouldReturnZero()
        {
            var dm = new DelegateMethod(i => !string.IsNullOrEmpty(i));

            var output = dm.SomeMethod(null);

            Assert.AreEqual(0, output);
        }
    }


We get the same result as the wrapper method – the test executes quickly, does not call the static method, and we can verify that the logic inside SomeMethod is correct.


Option 3 – Moles



Moles is an isolation framework from Microsoft that allows you to mock static method calls without rewriting any implementation code. You can even mock calls to .NET framework methods and properties, like DateTime.Now. The benefits are easy to write unit tests and less refactoring time, although at the expense of maintaining tightly-coupled code. Another drawback of Moles I’ve experienced is that it does not work well in a team environment with Team Foundation Server, because it creates proxy DLLs that are hosted in your unit test project, and multiple users checking out and checking in these DLLs becomes a pain very quickly, especially since the default checkout action is an exclusive lock. However, if you’re a sole developer working on a project, it is a worthwhile choice.


You can download Moles (with or without Pex) from Microsoft Research’s Moles Project site. Make sure that you download the correct version for your CPU (x86 vs x64).


After installing, you can right click the reference to the library you’d like to mole in your unit test project, and select Add Moles Assembly.


image


Now that a Moles assembly has been added to the project, you can now create a unit test and mock that call. You must make sure to import the “.Moles” version of the namespace as seen in the example below. All types in the assembly that can be mocked begin with the letter “M”, and for static methods, the method becomes a property (named with the method name followed by all of the parameter types) that is of a delegate type. Then you can “set” that property to a new delegate, such as a lambda in the example below:


using SomeLibraryYouCantModify.Moles;

namespace LibraryTestProject
{
    [TestClass]
    public class MoledTests
    {
        [TestMethod]
        [HostType("Moles")]
        public void SomeMethod_GivenNull_ShouldReturnZero()
        {
            var c = new SomeUntestableClass();

            MSomeStaticClass.SomeStaticMethodString = i => !string.IsNullOrEmpty(i);

            var output = c.SomeMethod(null);

            Assert.AreEqual(0, output);
        }
    }
}


I’ve bolded the interesting lines. First, you have to import the “.Moles” namespace, as I mentioned earlier. Second, you must add the HostType(“Moles”) to any methods that are to be run in the Moles host. If a test method is not run in the Moles host, it will not be able to use the Moled type, and will let you know with an exception. Finally, the “SomeStaticClass” has a moled “MSomeStaticClass” that provides the mockable methods. The “SomeStaticMethod” method becomes “SomeStaticMethodString”, with the String being added to the name to represent the type of the first and only parameter to the method. This allows for method overloading, as different parameter types will cause different property names on the moled type. Then, the property is set to the given lambda, which is identical to the Delegates example above.


Conclusion



Out of the three methods, I end up preferring the Wrapper method the most, because it is easy to use with IoC containers and Moq. However, it is probably the most amount of work, because you have to create 2 new types, one for the wrapper class and the other for the interface. Also, it means that you have an entire type that has zero coverage, because you can not write unit tests for this wrapper class as it would call the static method.


The delegate method is great for one or two method isolation, as it’s easy to do, doesn’t need to involve the IoC container, and can be easily mocked with constructor overloads. However, it’s the least intuitive code to read, and is clunky to use for more than two method calls.


The Moles method is certainly clever and very impressive on first use. It works great for small projects with one developer, and can allow you to achieve greater code coverage very quickly. However, it is slower to start the unit test run due to the Moles host, it doesn’t help you decouple your code, and it is a pain for multiple developers working on the same project due to source control conflicts.


Obviously, the ideal situation is to have a non-static method to call. If you can get the developer of the library to do it for you, they can create a non-static version of the type/methods that are called by the static version, so that their existing static API is maintained and you get the benefit of being able to wire up the dependency with dependency injection. Clearly, though, this isn’t always possible.


Hope this helps!
Previous
Next Post »