Testing Private Methods/Member Variables – Should you or shouldn’t you

One of the often requested features of NUnit was the ability to test private member variables and private methods. I resisted because I always felt that if you limited yourself to the public interface that enabled you to freely change the implementation without having to change the tests. This I believe is a good thing because if the tests require a lot of maintenance you might be tempted to not do it.  However, the flip side of the equation is you may end up exposing a method or worse yet a member variable only for testability. The downside of this is that once it is present in the interface it could be used for something else. So, as usual there are arguments on either side.

.NET, through reflection, provides the ability to invoke private methods and see the values of private member variables so it is not impossible to do this even today. However, the unit testing tool in VS Team System has a built-in wrapper, called PrivateObject, to make the syntax a bit easier to digest.

Here is an example:

using Microsoft.VisualStudio.QualityTools.UnitTesting.Framework;

public class TestedClass
private bool privateField = true;
private bool PrivateMethod()

public class PrivateTest
private PrivateObject privateObject;

public void Initialize()
TestedClass testedClass = new TestedClass();
privateObject = new PrivateObject(testedClass);

public void PrivateField()
bool field = (bool)privateObject.GetField(“privateField”);

public void PrivateMethod()
bool result = (bool)privateObject.Invoke(“PrivateMethod”);

As with all capabilities there is a right time and a wrong time to use them. I will be spending more time on this over the next few weeks but I would really like to get your feedback about this and recommendations on practice.

This posting is provided “AS IS” with no warranties, and confers no rights.

Comments (19)

  1. Todd says:

    I am split on whether or not we should be performing tests on private members. When I was first introduced to TDD by a former coworker, his philosophy was "develop for testability". And this would involve exposing members just for the purpose of developing tests against them. Of course, I have come to realize this is a horrible idea. If I were to lean one way, I would say testing only the public interfaces is the way to go. When someone consumes your object, they are only using the public interfaces so writing tests against these members makes sense. However, I can also understand the argument to hit against the private members.

  2. That’s pretty nice. In 99 out of 100 cases, I’d agree that your setting yourself up for a world of hurt if you test this way. It would be better to refactor your code so that the private code gets tested via the appropriate usage of the public interface.

    However, this is nice for that 1 case in 100 when you really need to get at the private members to save time in writing tests.

  3. kevin white says:

    When all you have is a hammer….

    The internals of an object certainly should be tested in some way. But unit tested? I don’t think so.

  4. I like to write all my tests as a part of my class that I am working on. This requires me to have #ifdef all over the place, but I don’t mind too much.

    That said, I do not test member variables. I only test functions/properties.

    I don’t like having to make things marked as internal, public just so that I can test it. But I also do test things marked as protected and private. If I have my tests at a granular level, I may have to change my tests more often, but they are more akin to what I would do debugging.

    I will experiment with the idea of only testing public interfaces.

  5. Darren Oakey says:

    There is another option here.

    I believe that

    a) it is an offense to test below the public interface

    b) we should be aiming at 100% test coverage?

    ie – every private method should be tested, BUT THROUGH THE PUBLIC INTERFACE. There is _no excuse_ for white box testing – the whole point is that we want to be able to refactor without changing our tests, so you actually decrease stability by allowing white-box testing, because programmers get used to changing unit tests when things go wrong..

    However, through the use of smart testing and coverage tools, you should be able to create situations through the public interface that exercise every private field and method. (And if you can’t – they shouldn’t be there!!!)

  6. Jay Bazuzi adds some additional information on his blog, check it out.


  7. Clark says:

    While I think this should be rarely used, I think that its important to have the ability to test private methods in certain cases.

    Where can I find PrivateObject? Team System is not available yet to the public, right? The best I could find was: http://weblogs.asp.net/stevencohn/archive/2004/06/08/151235.aspx and that isn’t quite the same as the above.