.Net Tips – using InternalsVisibleTo attribute to help testing non-public methods

Oh, the Pain!

For a long time, unit testing non-public methods in C# has been a pain in the back side. In order to test a non-public method (most likely private methods) you have a number of choices each with an undesired effect:

  1. The easiest way out is to make the methods public. However, this breaks all the encapsulations in your application and can be potentially unsafe because in most cases these methods were not exposed publicly for a reason, e.g. a method which can leave your application in a bad state if used incorrectly.
  2. If making the methods public is a step too far, you can make these methods protected instead and have the unit test class extend this class to gain access to the protected methods. Still, this breaks the encapsulation in your application somewhat, and having a unit test class extend a business logic class ‘smells’. And once again, it can be unsafe as others can also extend your class to gain unintended access to these methods, the same reason why you would often want to seal the LAST type in an inheritance hierarchy – to mark and protect the boundaries of your application.
  3. The last and the most advanced technique is to use reflection to invoke these methods. The upside is that you won’t have to break the encapsulation of your application just to make them testable, the downside is that you pay for this in maintainability and complexity. What it means is that your test class now needs to have intimate knowledge of the class it is testing and because methods names are spelled out in string literals, renaming the non-public method becomes a more costly operation because you need to change all the reflection code used to invoke the method too. Personally this is my least favourite approach as the frequency of change and the number of unit tests in any sizable project can make the task of maintaining them rather unenviable (especially if it’s your job to do so!).

There’s a better way

Since .Net 2.0, you have another alternative thanks to the introduction of the InternalsVisibleTo attribute. It gives you the ability to expose methods marked internal to a specific assembly.

All you need to do is add one line of code to the AssemblyInfo.cs file of the assembly (say, MyApplicatoin) you want to test to allow your unit test assembly (let’s call it MyApplication.Test) to see all the types/methods that have been marked with the internal access modifier:

[assembly: InternalsVisibleTo("MyApplication.Test")]

You will also need to change the access modifier on any methods (in MyApplication) you wish to test to internal for you to be able to see it in MyApplication.Test.

Doing so, however, doesn’t stop you from sealing your type (point 2 above) and doesn’t break all the encapsulation of your application (methods are still inaccessible from external assemblies besides the unit test assembly) although it still breaks the encapsulation of your type because any private methods you wish to test have to be made internal instead and therefore accessible from outside the type.

This is still not ideal, but compared to the alternatives, is still the one that I’m most willing to live with.

Parting thoughts…

Before you jump in with both feet and start testing all the private/internal methods, there’s a couple of questions you should always ask yourself first:

  1. The most important question of them all is whether or not these methods are even worth testing!
  2. If they are worth testing, could they be moved into a separate class?
  3. Could you cover all the test cases by making more calls to the public methods that call the private methods?

Testing with Pex

Some time ago I read about (might be on DotNetRocks) a little gem coming out of Microsoft’s research lab called Pex, which is a framework for doing automated White Box Testing in .Net. It’s still in its early days (despite having been around for more than 2 years now) but packs a bag of potential judging by what I’ve seen of the demo materials and been able to use myself!

In short, Pex is able to analyze your methods and work out the boundary conditions, etc. and derive a series of tests that can be used to test your method with as high a coverage as possible. The download package also includes a lightweight framework for test stubs and detours (which basically allows you to replace any .Net method with your own delegate) called Stubs and Moles. It also comes with the ability to automatically generate test project for you in MSTest and NUnit though I haven’t tested out the NUnit generation as it didn’t support NUnit generation the last time I played around it.

I won’t go into detail on how to use it as there are a ton of documentation and demo material on its site and I have barely scratched the surface myself, but do check it out if you haven’t done so already!