Test a public method which calls a private method using NUnit

Siddhant picture Siddhant · Jul 9, 2015 · Viewed 10.1k times · Source

I have a public method in a class that internally calls a particular private method within that class. It looks something like this :

public class MyClass : IMyClassInterface
{
    public List<int> MyMethod(int a, int b)
    {
        MyPrivateMethod(a, b, ref varList, ref someVal);
    }
    private void MyPrivateMethod(int a, int b, ref List<int> varList, ref double someval)
    {
    }
}

Now, I basically want to test this public method using NUnit. I am using NMock 2.0 for mocking. How do I do it? Since, it internally calls this private method which I do not want to make public. Or is there a way to do it if I turn the private method to protected instead?

Answer

k.m picture k.m · Jul 9, 2015

Now, I basically want to test this public method (...)

This is great. This is what you should be doing. Forget about internal details for a moment. From public method point of view, is there any difference between these two snippets?

// Your current implementation
public void MyMethod(int a, int b)
{
    MyPrivateMethod(a, b);
}
private void MyPrivateMethod(int a, int b)
{
    var c = a + b;
    // some more code
}

// Private method inlined
public void MyMethod(int a, int b)
{
    var c = a + b;
    // some more code
}

Whoever calls (public) MyMethod will not be able to notice any difference between these two. End result is the same. It doesn't matter there is a private method call, because as far a public API is concerned it is irrelevant. You could inline said private method, make it gone forever, and from public consumer point of view nothing changes. End result is the only thing that's important. You test end result observable by code consumer. Not some internal gibberish.

Important realization is this:

Properly designed SOLID code will never put you in a position which will require you to do private mocking. Source of the problem? Bad design.

Source: How to mock private method - solutions

Yep. Sad but true, your design is not that great. Depending on whether you want to change that or not, there are few approaches you could take:

  • don't try to mock private details, focus on public API (doesn't help with design issue)
  • extract private method to class, introduce dependency (long-term solution, improves design and makes code easily testable)
  • make private method protected, override in test as suggested in other answer (doesn't help with design issue, might not yield valuable test)

Whichever you chose I leave up to you. However, I'll emphasize it one more time - mocking private method is not unit testing, library or tools problem - it is a design problem and is best solvable as such.


On a side note, (if you can) don't use NMock2. It's a library with last changes from 2009. It's like having a 30 year old car which was last serviced 15 years ago. There are much better ones nowadays (FakeItEasy, Moq, NSubstitute).