23

I am writing unit test cases with the help of NUnit and have some static classes that I need to mock to run test cases so can we mock static class with the help of MOQ mocking framework?

Please suggest If some have idea.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
mahesh sharma
  • 998
  • 1
  • 7
  • 21
  • Possible duplicate of [Mocking Static Methods](https://stackoverflow.com/questions/5864076/mocking-static-methods) – jdphenix Oct 18 '17 at 03:01
  • 1
    Just out of curiosity, are you storing state in the class, or is it just a bunch of functional methods? If you're storing state, I'd recommend converting it to a non-static class, and just using something like a DI util for _injecting_ a singleton. Or am I missing the mark on your objective? – PSGuy Oct 18 '17 at 03:18
  • 1
    @PSGuy I have AppLog class which have static method to write logs so do we need to wrap that class into non static class to mock? – mahesh sharma Oct 18 '17 at 03:23
  • Based on what you've described, I wouldn't bother with mocking; I'd just use an interface, and use a NOOP. The static class can be just that - a static class, but you can come up with an interface for the log function, and an implementation that just calls the static class methods. That said, I'd highly recommend just using NLog. It's a solid framework, and seems to be well tested. – PSGuy Oct 18 '17 at 03:29
  • @maheshsharma You can try using a commercial product such as [Typemock](https://www.typemock.com/docs?book=Isolator&page=Documentation%2FHtmlDocs%2Fdefiningadefaultbehaviorforstaticmethods.htm). It's not cheap but you won't bloat your test code. – Sam Oct 30 '17 at 12:31

1 Answers1

22

There are two ways to accomplish this - As PSGuy said you can create an Interface that your code can rely on, then implement a concrete that simply calls the static method or any other logging implementation like NLog. This is the ideal choice. In addition to this if you have lots of code calling the static method that needs to be tested you can refactor your static method to be mocked.

Assuming your static class looks something like this:

public static class AppLog
{
    public static void LogSomething(...) { ... }
}

You can introduce a public static property that is an instance of the Interface mentioned above.

public static class AppLog
{
    public static ILogger Logger = new Logger();

    public static void LogSomething(...)
    {
        Logger.LogSomething(...);
    }
}

Now any code dependent on this static method can be tested.

public void Test()
{
    AppLog.Logger = Substitute.For<ILogger>(); // NSubstitute

    var logMock = new Mock<ILogger>();         // Moq
    AppLog.Logger = logMock.Object;            // Moq 

    SomeMethodToTest();

    AppLog.Logger.Recieved(1).LogSomething(...); // NSubstitute

    logMock.Verify(x => x.LogSomething(...));    // Moq
}
Aaron Roberts
  • 1,342
  • 10
  • 21
  • Thans Aaron, very helpful ! – cd491415 Feb 06 '19 at 00:55
  • Sorry about commenting so much time after answering, but I cannot understand why the Logger property in AppLog is not private? If it's just for the unit test, isn't it an anti-pattern? – Itiel Nov 27 '19 at 15:05
  • 1
    You could easily make it private with a public setter method. That would accomplish the same. There just needs to be a way to set it so that it can be mocked. – Aaron Roberts Nov 27 '19 at 15:10