Accessing Private Methods From Unit Tests

Summary

In this post, I’m going to show how to write a unit test that can access a private method of an object under test.  There is a lot of debate about whether private methods should be accessed from unit tests or that they should be either not tested, or made public.  I’m going to ignore the “debate” and just show the mechanics.  I’ll leave it up to you to decide if this is evil or not.

Non-Static Private Methods

I setup a demo application to show how to do both static and non-static.  I’m going to start with the non-static implementation.  Here’s the object I’m going to use.  I’ve dumbed it down to something really easy:

public class Mathinator
{
    private double AddList(double[] inputs)
    {
        double total = 0;

        foreach (var item in inputs)
        {
            total += item;
        }

        return total;
    }
}

You can use your imagination on how the “AddList” method is used as an internal object method and there is some reason you want to protect this method from being executed from another object.  Anyway, here’s how to write a unit test to execute this method and test the return value:

[TestMethod]
public void TestPrivateMethod()
{
    double [] input = new double [3];
    input[0] = 3;
    input[1] = 12.4;
    input[2] = 3.45;

    Mathinator mathinator = new Mathinator();
    var mathinatorObject = new PrivateObject(mathinator);
    double result = (double)mathinatorObject.Invoke("AddList",input);

    Assert.AreEqual(18.85, result);
}

The object “mathinator” can be used in your unit test to call any public methods as well, and all internal object results are updated when the Invoke command is called.  In this instance, I’m only Invoking the private method, recording the result and executing an assert command.

Static Private Methods

Now it’s time to show an example of how to execute a static private method.  Here’s the example object I used for this unit test:

public static class  StaticMathinator
{
    private static double AddNumbers(double[] inputs)
    {
        double total = 0;

        foreach (var item in inputs)
        {
            total += item;
        }

        return total;
    }
}

Again, this is a very simple example.  In order to invoke the static private method you’ll need to use the PrivateType instead of PrivateObject:

[TestMethod]
public void TestStaticPrivateMethod()
{
    double[] input = new double[3];
    input[0] = 3;
    input[1] = 12.4;
    input[2] = 3.45;

    var privateHelperType = new PrivateType(typeof(StaticMathinator));
    double result = (double)privateHelperType.InvokeStatic("AddNumbers", input);

    Assert.AreEqual(18.85, result);
}

Note: 

You can use the Invoke and InvokeStatic methods without parameters for private methods that don’t require parameters, and you can ignore the return parameter if your private method does not return a value.

Download the Sample Code

You can download the sample code at my github account by clicking here and experiment with it.

Leave a Reply