Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best practice for unit testing private methods in .NET?

Recently in order to implement unit testing for a private method of a class, I used PrivateObject by creating a private accessors instead of using Reflection, to which I received the following code review comment:

"My main concern with Private Object is the use of object[] in constructor. It replaces strong typing enforced by compiler with JavaScript-style run-time error detection.Consequently , personally, I would not recommend it."

This comment above confused me beacuse as per my understanding, Reflection also needs the object[] to invoke any method. Please help me to understand what the best approach is.

like image 488
Chirag Bhavsar Avatar asked Dec 17 '22 17:12

Chirag Bhavsar


2 Answers

  • You can use special classes that inherit classes with private (now protected) methods and provide public methods that call invisible from outside protected methods.

This is called Test Specific Subclass or Test Specific Extension in great book Refactoring Test Code http://xunitpatterns.com/

You can read more details and ideas for testing private methods here : http://xunitpatterns.com/Test-Specific%20Subclass.html

It works like

public TestClass : RealClass
{
    public int  CallHiddenCalculate()
    {
        return  Calculate(); // Calculate is now protected method that we expose for test purposes in this class
    }
}

You can place this class to test assembly so your real assembly doesnt contain test specific logic and classes because its bad design.

  • You can also use conditional compilation for visibility attribute like the following
    #if DEBUG
        public
    #else
        private
    #endif

In this case in Debug you can call unit tests but in release those methods won't be visible. However this approach is much worse than the above and is more ugly too.

Testing just public interface can easily be not enough (and often is not) in order to say that you got good test coverage and your code is easy to maintain and refactor.

As for marking private methods as internal and having test assembly see internal methods is bad for many reasons

  1. your ex private methods are visible from your assembly cause they are internal
  2. you will have test specific logic (internal for those methods will only be for test purposes) in release version of your product, which is bad

and I think there are more but those are most important

like image 152
Valentin Kuzub Avatar answered Feb 23 '23 01:02

Valentin Kuzub


Interesting question. Generally, unit tests are meant to verify the public behavior of your classes, from the viewpoint of consumers of your classes. That is, the consumers don't care HOW you do it, so long as your class keeps the promises it makes.

If you REALLY need to expose 'private' members to unit test, mark them as internal and make them accessible via the InternalsVisibleTo attribute. It's ugly, but it works, and you can later keep it out of your assembly with some conditional compilation.

like image 38
anon Avatar answered Feb 23 '23 00:02

anon