Test Private Methods with C#

unit test
c-sharp

TL;DR

This extension will allow any object to invoke a private method RunPrivateMethod().

public static class TestHelpers
{
    public static object RunPrivateMethod(this object obj, string methodName, params object[] args)
    {
        var method = obj
            .GetType()
            .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
        if (method == null)
        {
            throw new ArgumentException(
                $"{obj.GetType()} does not contain the method {methodName}", 
                "methodName"
            );
        }
        return method.Invoke(obj, args);
    }
}
Use it like this
var res1 = obj.RunPrivateMethod("SecretInternalMethod");
var res2 = obj.RunPrivateMethod("SecretInternalMethodWithArgs", arg1, arg2);

Explanation

The magic happens mainly with BindingFlags.NonPublic | BindingFlags.Instance which allows us to use reflection to get the MethodInfo for the specified private method.

Don't forget to include using statemnets using System; and using System.Reflection;

Usage

The following usage example shows how this could be used in a unit test
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    private string GetFullName() // <-- Private Method
    {
        return $"{FirstName} {LastName}";
    }

    private string GetFullNameWithNickname(string nickname) // <-- Private Method with argument
    {
        return $"{FirstName} '{nickname}' {LastName}";
    }
}

[Fact]
public void GetFullName__Should_Return_ExpectedResult()
{
    // ARRANGE
    var test = new Person { FirstName = "Ace", LastName = "Rimmer" };

    // ACT
    var name = test.RunPrivateMethod("GetFullName"); // <-- without args
    var nickname = test.RunPrivateMethod("GetFullNameWithNickname", "what a guy!"); // <-- with args
    
    // ASSERT
    name.Should().Be("Ace Rimmer");
    nickname.Should().Be("Ace 'what a guy!' Rimmer");
}