Any developer that you speak to, will tell you the importance of unit testing, not only its a check against your logic, but it also avoids bugs and helps you to have confidence in your work that goes into production.

Usually when creating private methods within a class, that private method is tested by covering the public method(s) that calls the private method. But in some cases, if you just want to write unit tests to validate that your private method is doing what it is supposed to do, then this article is for you.

Let's say, your solution has a separate unit test project per project. A sample structure would be something like this.

project structure

It is impossible to unit test private methods as their access level is specifically limits them from being accessed outside of the class where they reside. Changing the access modifier not to public but with less access is the only way possible to achieve this.

Lets say you need to verify a private method like the below one.

public class HelloService : IHelloService
{
    public void WriteMessage()
    {
        Console.WriteLine(GetMessage());
    }

    private string GetMessage()
    {
        return "Hello World!";
    }
}

And you would write a unit test like the below. At this point it will NOT compile as this method is not accessible by the test class.

[Fact]
public void When_WriteMessage_Called_Then_Verify_GetMessage()
{
    //arrange
    var expectedResult = "Hello World";
    //act
    var result = _helloService.GetMessage();
    //assert
    result.Should().Be(expectedResult);
}

Change Private to Protected

The best way to do this, is to change the private method to protected. That means it can only be accessed by that class and any class that inherits the class where the method lives in.

[There is another unsafe option, which is to make it internal and make the assembly's internal visible to the unit test assembly. But we will avoid that as making the method internal makes it accessible within the whole assembly.]

Lets do this by first changing the method to protected

protected string GetMessage()
{
    return "Hello World!";
}

Then lets create a wrapper that inherits the class (not the interface) where this method resides in.

public class HelloServiceTestsWrapper : HelloService
{
    public new string GetMessage()
    {
        return base.GetMessage();
    }
}

Now lets again connect this wrapper into our unit tests and your tests now will look like this.

[Fact]
public void When_WriteMessage_Called_Then_Verify_GetMessage()
{
    //arrange
    var expectedResult = "Hello World";
    //act
    var result = _helloServiceWrapper.GetMessage();
    //assert
    result.Should().Be(expectedResult);
}

Now you can test your private protected method to your hearts content. if you got questions please fell free to leave a comment below. I will do my best to answer them.