January 16, 2013

Unit testing private static methods in Visual Studio 2012

Filed under: Tips — Tags: , — Webopius @ 3:52 pm

Unit Testing and Test Driven (Test First) Development are becoming absolutely mandatory activities in Software Development. Visual Studio includes the excellent Test Explorer unit testing framework to make building and running Unit Tests very straightforward.

However, in Visual Studio 2012, Microsoft have removed the feature where you used to be able to right-click on a method and choose ‘Generate Unit Test’. Now, you have to write your own tests from scratch.

This is all fine until you want to write Unit Tests for private class methods. In the old days, Visual Studio would figure out all of the reflection and so on and you’d just have to write the test code. In Visual Studio 2012, the recommended approach is now to use the ‘PrivateObject’ and ‘PrivateType’ classes within the UnitTesting framework.

One area in particular where the approach isn’t well documented is how to create a unit test for a method that’s both Private and Static. Here’s the solution:

In this simple example, we have the following class with one private static method called ‘ValidateCommand’:

public class WebServiceClient
{
    private static bool ValidateCommand(String Command)
    {
	bool result = false;
	switch (Command) {
		case "getpage":
		case "getpost":
		case "getpostimage":
		case "getposts":
		case "getcomments":
		result = true; break;
	}
	return result;
	}
}

In the real world, the WebServiceClient class has other methods that make use of this private method to check a command is valid.

Now, to create a Unit Test to test that ValidateCommand returns false when an incorrect command string is passed, looks like this:

[TestMethod]
public void TestInvalidCommand()
{
    String Command = "InvalidCommandName";
    PrivateType pt = new PrivateType(typeof(WebServiceClient));

    bool actualresult = (bool)pt.InvokeStatic("ValidateCommand", new object[]{Command});
    bool expectedresult = false;
    Assert.AreEqual(actualresult, expectedresult);
}

Note the use of ‘PrivateType’ and ‘InvokeStatic’ rather than the usual ‘PrivateObject’ and ‘Invoke’.

…and to test for the range of Valid commands…

[TestMethod]
public void TestValidCommands()
{
    List<String> validcommands = new List<String>();
    validcommands.Add("getpage");
    validcommands.Add("getpost");
    validcommands.Add("getpostimage");
    validcommands.Add("getposts");
    validcommands.Add("getcomments");

    PrivateType pt = new PrivateType(typeof(WebServiceClient));

    foreach (String command in validcommands)
    {
        bool actualresult = (bool)pt.InvokeStatic("ValidateCommand",
            new object[] { command });
        bool expectedresult = true;

        Assert.AreEqual(actualresult, expectedresult);
    }
}
  • Tags