I have a certain degree of sympathy with the view that if you need to do this then there’s something architecturally wrong. But the question came up recently and those familiar with the code were adamant that it was as well factored as it could be. Unfortunately it wasn’t very clear how to test such a method.

So we have a class and a method.

abstract class Base
{
    private int Double(int x)
    {
        return x * 2;
    }
}

class Derived : Base
{
}

The stumbling point is that clearly an instance of Derived does not have access the private methods of Base, and that you can’t get an instance of Base as that’s abstract. The auto-generated templates provided by Visual Studio leave a few too many // TODOs to be particularly useful.

The crudest method is plain old reflection:

[TestMethod]
public void ReflectionTest()
{
    var target = new Derived();
    var method = target.GetType().BaseType.GetMethod("Double", BindingFlags.NonPublic | BindingFlags.Instance);
    var result = method.Invoke(target, new object[] { 2 });
    Assert.AreEqual(4, result);
}

Note that we are use .BaseType to walk up the hierarchy.

The Visual Studio Unit Test libraries have a PrivateObject accessor that wraps this much more nicely

[TestMethod]
public void PrivateObjectTest()
{
    var target = new PrivateObject(new Derived(), 
                                   new PrivateType(typeof(Base)));
    var result = target.Invoke("Double", 34);
    Assert.AreEqual(68, result);
}

Or if you use the accessor assemblies you can do

[TestMethod]
public void AccessorTest()
{
    var target = new Base_Accessor(new PrivateObject(new Derived(), 
                                   new PrivateType(typeof(Base))));
    Assert.AreEqual(2, target.Double(1));
}

If you find you are doing this a lot then in the brave new world of C# 4 you could use dynamics to make it a little slicker still

[TestMethod]
public void DynamicTest()
{
    dynamic target = new DynamicAccessor(new Derived(), typeof(Base));
    Assert.AreEqual(90, target.Double(45));
}

This relies on a DynamicAccessor class of the following form:

class DynamicAccessor : DynamicObject
{
    private PrivateObject privateObject;

    public DynamicAccessor(object d)
    {
        this.privateObject = new PrivateObject(d);
    }

    public DynamicAccessor(object d, Type t)
    {
        this.privateObject = new PrivateObject(d, new PrivateType(t));
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder,
                                          object[] args,
                                          out object result)
    {
        try
        {
            result = privateObject.Invoke(binder.Name, args);
            return true;
        }
        catch (MissingMethodException)
        {
            result = null;
            return false;
        }
    }
}