Unit testing private methods in C# With XUnit | 2023

Unit testing private methods in C# can be a challenging task as private methods are not directly accessible from outside the class. However, there are several techniques available to test private methods in C#, including Reflection, Accessors, and Protected Method Testing.

By the end of this article, you will have a better understanding of how to test private methods using XUnit in C# and be equipped with the knowledge to write effective unit tests for your C# projects.

Diffrent Ways of Testing Private Methods in XUnit

Testing private methods is often considered an anti-pattern, as it can lead to tests that are tightly coupled to the implementation details of the code. However, several techniques can be used to test private methods if it’s necessary.

  1. Reflection: One common way of testing private methods in C# is to use reflection to access the private method and invoke it with the appropriate parameters. This approach can be useful, but it’s important to note that it can also be risky, as changes in the implementation details can break the tests.
  2. Protected Method Testing: Another technique for testing private methods is to make the method protected and then create a derived class in the test project that exposes the method. This approach is known as the “Protected Method Testing” pattern. However, it can lead to an increase in code complexity and can violate the encapsulation principle.
  3. Accessors: Another approach is to use accessors, which are generated by Visual Studio when you create a project that uses the .NET Framework. Accessors are special classes that are generated to expose private methods and properties, making it possible to test them. This approach can be useful, but it can also lead to code bloat, as the generated code can be quite verbose.
  4. Use public methods that call the private methods: If a private method is only called from public methods, we can test the public methods and indirectly test the private methods. This approach is often more effective than testing private methods directly, as it ensures that the tests are focused on the public API of the code.

Here are some code examples for each technique and how they can be used to test private methods in C#.

Consider a class that manages employee details, which includes a private method called GetEmployeeId that generates a unique employee id for each employee. The GetEmployeeId method is not exposed publicly and is only used internally within the class to generate ids. We can use various techniques to test this private method and ensure it is working correctly.

public class EmployeeManager
{

    public EmployeeManager()
    {
        
    }

    public void SaveEmployee(string name, string email, string contactNo)
    {
        var empId = GetEmployeeId();
    }

    private string GetEmployeeId()
    {
        return  Guid.NewGuid().ToString();
    }
}

Test Private Methods Using Xunit and Reflection

we can use reflection to test the GetEmployeeId private method. Here’s an example of how we can use reflection to test the private method:

public class EmployeeManagerTests
{
    [Fact]
    public void GetEmployeeId_Should_GenerateUniqueGuide()
    {
        // Arrange
        var obj = new EmployeeManager();
        var methodInfo =
            typeof(EmployeeManager).GetMethod("GetEmployeeId", BindingFlags.NonPublic | BindingFlags.Instance);

        // Act
        var response = methodInfo.Invoke(obj, null);

        Assert.NotNull(response);
    }
}

Test Result:

Test Private Method Using Reflection in Xunit framework with C#

Protected Method Testing in XUnit

Assume the GetEmployeeId method was protected in EmployeeManager instead of private. It would have little bit easier for us to test them because protected methods are exposed at least in child classes.

public class EmployeeManager
{

    public EmployeeManager()
    {
        
    }

    public void SaveEmployee(string name, string email, string contactNo)
    {
        var empId = GetEmployeeId();
    }

    protected string GetEmployeeId()
    {
        return  Guid.NewGuid().ToString();
    }
}

We need to update the EmployeeManagerTests class inherited from the EmployeeManager class and that’s it we will have the accessibility of the GetEmployeeId method to access and write the test cases around it.

public class EmployeeManagerTests: EmployeeManager
{
    [Fact]
    public void GetEmployeeId_Should_GenerateUniqueGuide()
    {
        // Arrange
        var response = GetEmployeeId();

        Assert.NotNull(response);
    }
}

Test Private Methods using Accessor Classes in Xunit

PrivateAccessor classes are utility classes that provide helper methods to access private or protected methods within a class. I have used one of the NuGet packages to get the benefit of the already available PrivateAccessor class.

dotnet add package Rees.UnitTestUtilities --version 1.1.7

Let’s update the EmployeeManagerTests class to utilize the PrivateAccessor class and test the GetEmployeeId method.

public class EmployeeManagerTests
{
    private readonly EmployeeManager _manager=new();

    [Fact]
    public void GetEmployeeId_Should_GenerateUniqueGuide()
    {
        // Arrange
        var response = PrivateAccessor.InvokeFunction<string>(_manager, "GetEmployeeId", null);
        Assert.NotNull(response);
    }
}

This is one example of utilizing the PrivateAccessor utility class. However, it has a lot more methods and functions provided to faster the process of writing the unit test cases.

Unit testing private methods in C# With XUnit | 2023 1

Test Private Methods Using Public Methods in Xunit

To demonstrate this approach I have modified the EmployeeManager class a little bit. Created an entity class that will be used for storing the employee details and the same details will be sent back to the caller.

public class Employee
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Contact { get; set; }
    public string Id { get; set; }
}
public class EmployeeManager
{

    public Employee SaveEmployee(string name, string email, string contactNo)
    {
        var empId = GetEmployeeId();
        var empRecord = new Employee()
        {
            Name = name,
            Email = email,
            Contact = contactNo,
            Id = empId
        };

        //Database logic to save Employee 

        return empRecord;
    }

    private string GetEmployeeId()
    {
        return  Guid.NewGuid().ToString();
    }
}

Now we have to update the EmployeeManagerTest class as well to write the unit test which will indirectly test the GetEmployeeId method.

public class EmployeeManagerTests
{
    private readonly EmployeeManager _manager=new();

    [Fact]
    public void SaveEmployee_Should_Return_EmployeeId()
    {
        // Arrange
        var emp = _manager.SaveEmployee("Deependra", "K", "98765433456785678");
        Assert.NotNull(emp.Id);
    }
}
Test Private Methods Using Public Methods in Xunit

Conclusion

In conclusion, there are three main approaches to testing private methods: Reflection, Accessors, and Protected Method Testing. We have gone through each one of them and tried understanding them with examples.

Ultimately, the choice of approach will depend on the specific situation and context of the project. In some cases, it may be best to avoid testing private methods directly and instead focus on testing through public methods or creating a more modular design.

Scroll to Top