Mocking Static Methods
Recently, I've begun to use Moq to unit test. I use Moq to mock out classes that I don't need to test.
How do you typically deal with static methods?
public void foo(string filePath)
{
File f = StaticClass.GetFile(filePath);
}
How could this static method, StaticClass.GetFile()
get mocked?
P.S. I'd appreciate any reading materials you recommend on Moq and Unit Testing.
@Pure.Krome: good response but I will add a few details
@Kevin: You have to choose a solution depending on the changes that you can bring to the code.
If you can change it, some dependency injection make the code more testable.
If you can't, you need a good isolation.
With free mocking framework (Moq, RhinoMocks, NMock...) you can only mock delegates, interfaces and virtual methods. So, for static, sealed and non-virtual methods you have 3 solutions:
- TypeMock Isolator (can mock everything but it's expensive)
- JustMock of Telerik (new comer, less expensive but still not free)
- Moles of Microsoft (the only free solution for isolation)
I recommend Moles, because it's free, efficient and use lambda expressions like Moq. Just one important detail: Moles provide stubs, not mocks. So you may still use Moq for interface and delegates ;)
Mock: a class that implements an interface and allows the ability to dynamically set the values to return/exceptions to throw from particular methods and provides the ability to check if particular methods have been called/not called.
Stub: Like a mock class, except that it doesn't provide the ability to verify that methods have been called/not called.
Mocking frameworks like Moq or Rhinomocks can only create mock instances of objects, this means mocking static methods is not possible.
You can also search Google for more info.
Also, there's a few questions previously asked on StackOverflow here, here and here.
There is possibility in .NET excluding MOQ and any other mocking library. You have to right click on solution explorer on assembly containing static method you want to mock and choose Add Fakes Assembly. Next you can freely mock that's assembly static methods.
Assume that you want to mock System.DateTime.Now
static method. Do this for instance this way:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => new DateTime(1837, 1, 1);
Assert.AreEqual(DateTime.Now.Year, 1837);
}
You have similar property for each static property and method.
You can achieve this with Pose library available from nuget. It allows you to mock, among other things, static methods. In your test method write this:
Shim shim = Shim.Replace(() => StaticClass.GetFile(Is.A<string>()))
.With((string name) => /*Here return your mocked value for test*/);
var sut = new Service();
PoseContext.Isolate(() =>
result = sut.foo("filename") /*Here the foo will take your mocked implementation of GetFile*/, shim);
For further reading refer here https://medium.com/@tonerdo/unit-testing-datetime-now-in-c-without-using-interfaces-978d372478e8