views:

12853

answers:

17

I'm building a class library that will have some public & private methods. I want to be able to unit test the private methods (mostly while developing, but also it could be useful for future refactoring).

What is the best way to do this?

+4  A: 

Declare them internal, and then use the InternalsVisibleToAttribute to allow your unit test assembly to see them.

James Curran
I don't like using InternalsVisibleTo because I made the method private for a reason.
swilliams
+24  A: 

You should use the InternalsVisibleToAttribute. How to apply it in unit tests: http://devlicio.us/blogs/derik_whittaker/archive/2007/04/09/internalsvisibleto-testing-internal-methods-in-net-2-0.aspx

TcKs
Yuck. This gets compiled into your released assemblies.
Jay
+64  A: 

If you want to unit test a private method, something may be wrong. Unit tests are (generally speaking) meant to test the interface of a class, meaning its public (and protected) methods. You can of course "hack" a solution to this (even if just by making the methods public), but you may also want to consider:

  1. If the method you'd like to test is really worth testing, it may be worth to move it into its own class.
  2. Add more tests to the public methods that call the private method, testing the private method's functionality. (As the commentators indicated, you should only do this if these private methods's functionality is really a part in with the public interface. If they actually perform functions that are hidden from the user (i.e. the unit test), this is probably bad).
Jeroen Heijmans
Option 2 makes the unit tests have to have knowledge of the underlying implementation of the function. I don't like doing that. I generally think unit tests should test the function without assuming anything about implementation.
Herms
Disadvantages of testing implementation is that the tests will be fragile to break if you introduce any changes to the implementation. And this is undesirable as refactoring is as important as writing the tests in TDD.
JtR
Well, the tests *are supposed* to break if you change the implementation. TDD would mean changing the tests first.
sleske
@sleske - I don't quite agree. If the *functionality* hasn't changed, then there's no reason the test should break, since tests should really be testing behaviour/state, not implementation. This is what jtr was meaning about it making your tests fragile. In an ideal world, you should be able to refactor your code and have your tests still pass, verifying that your refactoring hasn't changed the functionality of your system.
Alconja
@sleske and @alconja/jtr - i think you both mean diff things by break - sleske - test failures. alconja/jtr mean compile failures. private methods undergo rapid refactoring.. tests that have knowledge of the private methods thereby tend to be fragile.. as in you need to go back and modify the test code with changes in implementation. The righteous path :) is that a test shouldn't have to change unless the requirement/functionality/behavior changes
Gishu
+4  A: 

I've also used the InternalsVisibleToAttribute method. It's worth mentioning too that, if you feel uncomfortable making your previously private methods internal in order to achieve this, then maybe they should not be the subject of direct unit tests anyway.

After all, you're testing the behaviour of your class, rather than it's specific implementation - you can change the latter without changing the former and your tests should still pass.

Phil Nash
+3  A: 

I tend not to use compiler directives because they clutter things up quickly. One way to mitigate it if you really need them is to put them in a partial class and have your build ignore that .cs file when making the production version.

swilliams
+5  A: 

In the rare cases I have wanted to test private functions, I have usually modified them to be protected instead, and the I have written a subclass with a public wrapper function.

The Class:

...

protected void APrivateFunction()
{
    ...
}

...

Subclass for testing:

...

[Test]
public void TestAPrivateFunction()
{
    APrivateFunction();
    //or whatever testing code you want here
}

...
Jason Jackson
+3  A: 

MS Test has a nice feature built in that makes private members and methods available in the project by creating a file called VSCodeGenAccessors

[System.Diagnostics.DebuggerStepThrough()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
    internal class BaseAccessor
    {

        protected Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject m_privateObject;

        protected BaseAccessor(object target, Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
        {
            m_privateObject = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(target, type);
        }

        protected BaseAccessor(Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
            :
                this(null, type)
        {
        }

        internal virtual object Target
        {
            get
            {
                return m_privateObject.Target;
            }
        }

        public override string ToString()
        {
            return this.Target.ToString();
        }

        public override bool Equals(object obj)
        {
            if (typeof(BaseAccessor).IsInstanceOfType(obj))
            {
                obj = ((BaseAccessor)(obj)).Target;
            }
            return this.Target.Equals(obj);
        }

        public override int GetHashCode()
        {
            return this.Target.GetHashCode();
        }
    }

With classes that derive from BaseAccessor

such as

[System.Diagnostics.DebuggerStepThrough()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
internal class SomeClassAccessor : BaseAccessor
{

    protected static Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType m_privateType = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType(typeof(global::Namespace.SomeClass));

    internal SomeClassAccessor(global::Namespace.Someclass target)
        : base(target, m_privateType)
    {
    }

    internal static string STATIC_STRING
    {
        get
        {
            string ret = ((string)(m_privateType.GetStaticField("STATIC_STRING")));
            return ret;
        }
        set
        {
            m_privateType.SetStaticField("STATIC_STRING", value);
        }
    }

    internal int memberVar    {
        get
        {
            int ret = ((int)(m_privateObject.GetField("memberVar")));
            return ret;
        }
        set
        {
            m_privateObject.SetField("memberVar", value);
        }
    }

    internal int PrivateMethodName(int paramName)
    {
        object[] args = new object[] {
            paramName};
        int ret = (int)(m_privateObject.Invoke("PrivateMethodName", new System.Type[] {
                typeof(int)}, args)));
        return ret;
    }
Marcus King
The gen'd files only exist in VS2005. IN 2008 they're generated behind the scenes. And they're an abmomination. And the associated Shadow task is flaky on a build server.
Ruben Bartelink
+2  A: 
CC -Dprivate=public
Mark Harrison
What is this? Does this apply to Visual Studio?
YeahStu
"CC" is the command line compiler on the system I use. "-Dfoo=bar" does the equivalent of "#define foo bar". So, this compilation option effectively changes all private stuff to public. ha-ha!
Mark Harrison
In Visual Studio, set a define in your build environment.
Mark Harrison
+3  A: 

On CodeProject, there is an article that briefly discusses pros and cons of testing private methods. It then provides some reflection code to access private methods (similar to the code Marcus provides above.) The only issue I've found with the sample is that the code doesn't take into account overloaded methods.

You can find the article here:

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

Pedro
+1  A: 

MbUnit got a nice wrapper for this called Reflector.

Reflector dogReflector = new Reflector(new Dog());
dogReflector.Invoke("DreamAbout", DogDream.Food);

You can also set and get values from properties

dogReflector.GetProperty("Age");

Regarding the "test private" I agree that.. in the perfect world. there is no point in doing private unit tests. But in the real world you might end up wanting to write private tests instead of refactoring code.

Carl Bergquist
Just for info, `Reflector` has been replaced by the more powerful `Mirror` in Gallio/MbUnit v3.2. (http://www.gallio.org/wiki/doku.php?id=mbunit:mirror)
Yann Trevin
+2  A: 

Sometimes, it can be good to test private declarations. Fundamentally, a compiler only has one public method: Compile( string outputFileName, params string[] sourceSFileNames ). I'm sure you understand that would be difficult to test such a method without testing each "hidden" declarations!

That's why we have created Visual T#: to make easier tests. It's a free .NET programming language (C# v2.0 compatible).

We have added '.-' operator. It just behave like '.' operator, except you can also access any hidden declaration from your tests without changing anything in your tested project.

Take a look at our web site: download it for free.

Ludovic Dubois
+4  A: 

Private types, internals and private members are so because of some reason, and often you don’t want to mess with them directly. And if you do, chances are that you’ll break later, because there is no guarantee that the guys who created those assemblies will keep the private/internal implementations as such.

But ,at times, when doing some hacks/exploration of compiled or third party assemblies, I have myself ended up wanting to initialize a private class or a class with a private or internal constructor. Or, at times, when dealing with pre-compiled legacy libraries that I can’t change - I end up writing some tests against a private method.

Thus born the AccessPrivateWrapper - http://amazedsaint.blogspot.com/2010/05/accessprivatewrapper-c-40-dynamic.html - it's is a quick wrapper class that’ll make the job easy using C# 4.0 dynamic features and reflection.

You can create internal/private types like

    //Note that the wrapper is dynamic
    dynamic wrapper = AccessPrivateWrapper.FromType
        (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

    //Access the private members
    wrapper.PrivateMethodInPrivateClass();
amazedsaint
A: 

You could generate the test method for the private method from Visual studio 2008. When you create a unit test for a private method, a Test References folder is added to your test project and an accessor is added to that folder. The accessor is also referred to in the logic of the unit test method. This accessor allows your unit test to call private methods in the code that you are testing. For details have a look at

http://msdn.microsoft.com/en-us/library/bb385974.aspx

Sarath
+1  A: 

I don't agree with the "you should only be interested in testing the external interface" philosophy. It's a bit like saying that a car repair shop should only have tests to see if the wheels turn. Yes, ultimately I'm interested in the external behavior but I like my own, private, internal tests to be a bit more specific and to the point. Yes, if I refactor, I may have to change some of the tests, but unless it's a massive refactor, I'll only have to change a few and the fact that the other (unchanged) internal tests still work is a great indicator that the refactoring has been successful.

You can try to cover all internal cases using only the public interface and theoretically it's possible to test every internal method (or at least every one that matters) entirely by using the public interface but you may have to end up standing on your head to achieve this and the connection between the test cases being run through the public interface and the internal portion of the solution they're designed to test may be difficult or impossible to discern. Having pointed, individual tests that guarantee that the internal machinery is working properly is well worth the minor test changes that come about with refactoring - at least that's been my experience. If you have to make huge changes to your tests for every refactoring, then maybe this doesn't make sense, but in that case, maybe you ought to rethink your design entirely. A good design should be flexible enough to allow for most changes without massive redesigns.

Darrell Plank
A: 

For c++ did someone hear of friend modifier ?

andy
A: 

It might not be usefull to test private methods. However, I also sometimes like to call private methods from test methods. Most of the time in order to prevent code duplication for test data generation...

M$ provides two mechanisms for this:

Accessors

  • Goto the class definition's source code
  • Right-click on the name of the class
  • Choose "Create Private Accessor"
  • Choose the project in which the accessor should be created => You will end up with a new class with the name foo_accessor. This class will be dynamically generated during compilation and privides all members public available.

However, the mechanism is sometimes a bit intractable when it comes to changes of the interface of the original class. So, most of the times I avoid using this.

PrivateObject class The other way is to use Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject

// Wrap an already existing instance
PrivateObject accessor = new PrivateObject( objectInstanceToBeWrapped );

// Retrieve a private field
MyReturnType accessiblePrivateField = (MyReturnType) accessor.GetField( "privateFieldName" );

// Call a private method
accessor.Invoke( "PrivateMethodName", new Object[] {/* ... */} );
Seven