Unit Test Private Methods in Visual Studio

I am working on a feature that will let me import twitter messages to yonkly and wanted to write a test for it.  The method is private and I couldn’t get the unit test to see it.  I also didn’t want to use the private accessor class generate by Visual Studio because I was mocking some functionality in the actual class and didn’t really fell like re-mocking it on the private accessor.

So, after several minutes of googling, I found several solutions that I didn’t like.  John Hann uses reflection to test private methods.  Tim Stall has a similar solution at the code project.  Andrew Stopford suggested that I don’t test private methods and use code coverage to make sure that they are being exercised.  I was about to use the methods suggested by John Hann and Tim Stall to test my private methods, but then I accidentally (thanks to IntelliSense) discovered PrivateObject.

The PrivateObject class is part of the Team Test API.

Allows test code to call methods and properties on the code under test that would be inaccessible because they are not public.
from msdn

It turned out to be pretty easy to test private methods and the code looked like this:

var myController = new TwitterController();
var po = new PrivateObject(myController);
var page = 1;
var count = 25;
po.Invoke("ImportTweets", new object[] { page, count });

 

The code above will call the private method ImportTweets and pass it two integer parameters.  This is the equivalent of calling

myController.ImportTweets( page, count);

 

Note that this is essentially what John Hann and Tim Stall suggested but why use extra code when PrivateObject is already available for you.

Advertisements

0 thoughts on “Unit Test Private Methods in Visual Studio

  1. Pingback: Bookmarks about Mvc

  2. The downside to using PrivateObject is that it is a bit painful to maintain, since signature changes are not caught at compile-time, but instead caught at test-time. Refactorings that change method signatures tend to catch all the compile-time stuff, but then leave test code broken, and it is tougher to fix.An alternative that I've always liked is to use inner-classes to test your code, like this:public class Foo { private void Bar() { // Do so work here in a private method }#region Unit Tests#if UNIT_TESTS [TestFixture] public class TestFoo { [Test] public void TestBar() { Foo foo = new Foo() foo.Bar(); // inner class can call this method } } #endif#end region}You simply define UNIT_TESTS in Debug/Release builds if you want test code enabled, and leave it out from your Ship builds.Also, you'll probably have a using statement wrapper, #if UNIT_TESTSusing MbUnit.Framework;#endifAs an added check, you can write a simple app that does reflection on all the types in the DLL to verify your ship build doesn't have any classes with test attributes. If no code references the test framework, your ship builds will automatically not load the referenced test framework DLLs, thus allowing you to ship your product like usual without pulling in test DLL dependencies (and associated bloat and licensing issues).

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s