开发者

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 receive开发者_JAVA技巧d 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.


  • 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


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.


You are right that using reflection has much the same pitfalls as using the PrivateObject pattern. A better solution is to avoid trying to specifically test private methods.


In case you are using the Gallio/MbUnit testing framework, you might consider the built-in Mirror API.

Sometimes, the most obvious way to write a test is by accessing non-public state or behaviors. It may not be the best way to write the test but it may seem like the simplest solution for the time being. MbUnit provides a couple of classes to help access non-public members.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜