Sunday, January 17, 2010

TDD: Mock static method

Most of the Mock framework doesn’t support static method mocking. So most of the time you need to modify your code to make the code testable. I’m going to use Moq mocking framework to show mocking.

Class with static method:

public class MyHelper
{
public static string GetHelp()
{
return "This is help";
}
}

Class under test and using static methods

public class MyManager
{
public bool IsManaged { get; set; }
public void Manage()
{
string help = MyHelper.GetHelp();
IsManaged = (!string.IsNullOrEmpty(help));
}
}

In the above code, the static method call (MyHelper.GetHelp())need to be mocked. The problem is that MyHelper can’t be passed from outside and second problem is that Moq framework doesn’t have option to mock static method.

 

Approach to use to modify code to make static method mockable

Now let’s modify the code so that we can separate the static method invocation from our methods that we want to test. Let’s modify the MyManager class to make it testable.

1. Modify Code to separate dependencies on static methods:

In the following code snippet I have separated extracted a method in MyManager which will return the help. The extract method GetHelp method needs to be virtual and protected as this will be overridden by stub class.

public class MyManager
{
public bool IsManaged { get; set; }
public void Manage()
{
string help = GetHelp();
IsManaged = (!string.IsNullOrEmpty(help));
}

protected virtual string GetHelp()
{
return MyHelper.GetHelp();
}
}

2. Create a stub of the class under test in the test project

Now you can override the GetHelp method in the stub class as shown below. So your stub class is not using static method rather it’s doing something fake.

public class MyManagerStub:MyManager
{
protected override string GetHelp()
{
return "this is help from stub";
}
}

3. Test stub class instead of actual class

Now your stub class MyManageStub is alike the MyManager except the static method invocation is removed. Now you test will use MyManagerStub as shown below

public void TestMe()
{
MyManagerStub manager = new MyManagerStub();
manager.Manage();
Assert.AreEqual(true, manager.IsManaged);
}

The approach I have described in this post is a one of the approach taken from this link.

1 comment:

  1. Hi Rana,

    How do you mock the line "MyHelper.GetHelp()" without changing the actual TEST class.

    Please suggest.

    ReplyDelete