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?
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?
Declare them internal
, and then use the InternalsVisibleToAttribute
to allow your unit test assembly to see them.
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
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:
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.
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.
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
}
...
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;
}
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:
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.
This is a neat way of managing things:
http://elegantcode.com/2010/01/28/calling-non-public-methods/
And another:
http://elegantcode.com/2010/04/16/linfu-duck-typing-part-1-revealing-secrets/
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.
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();
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
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.
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
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[] {/* ... */} );