Unit Testing Internal Methods

dotcover-resultsI’ll come straight out with it, I don’t like unit tests residing within the dll that they are testing, I know that some people quite like this approach and it could be argued that it allows the clients to verify that the unit tests are indeed in place and working correctly. For me though they are not a part of the production code and just add unnecessary bloat to it, this is allied to the fact that sometimes test rely on the infrastructure and there may also be a set amount of database interaction which for a live client is a big no no!

Instead I prefer all of my unit tests to be in a single or suite of test projects that are invoked sometime during the build process to verify the quality of the code. Recently we have been retroactively fitting some unit-testing to new functionality within a legacy project (which means that we do not of course have dependancy injection!) and I came up against an issue that we have come up against before but have always cludged our way around. The issue is one of scope, I like to test the validation routines for the business layer in isolation but we never ordinarily make our business layer validation methods public instead relying on the main ‘Update’ method to perform the validation prior to save. I like to call the validation methods in isolation because it means that the tests are more performant which in turn means you can be more thorough and reap the rewards of a more stable and tested application. Ideally I like to make the validation methods private or protected but for the sake of unit testing I will compromise and make them internal, this way they can be invoked from anywhere within the business layer but NOT from outside. OK, now scan back to my first paragraph and you can see where my problem lies… I don’t like unit tests in the dll itself.

Luckily .NET has a solution to this problem in that internal methods may be made visible to named external libraries; thus our unit testing library can invoke the required validation methods without exposing the same methods in the public API. However, all of the examples I have seen for implementing this are very poorly documented and so I thought as an aide memoire for myself, and as a service to the internet at large I would share my experiences.

For the purposes of this discussion I have three projects, the three projects must either ALL be signed or ALL unsigned, no if’s no buts. For the purposes of this discussion I will be using signed assemblies.

  1. MyProject.Business which is where the business rules reside – “C:\My Projects\MyProject.Business”
  2. MyProject.UI which is where the main application user interface resides -“C:\My Projects\MyProject.UI”
  3. MyProject.UnitTests which is where all of my Nunit tests reside – “C:\My Projects\MyProject.UnitTests”

MyProject.Business has the following class defined within it:-

namespace MyProject {
  public class ContactsBusiness {

    public void Update(ContactsDS data) {
       ....... Code...


       ....... More Code....
    internal void ValidateContacts(ContactsDS data) {
       ....... Code...
    private void SomeTopSecretMethod(ContactsDS data) {
       ....... Code...

Now as things stand the only method visible to the external MyProject.UI and MyProject.UnitTests is the main Update method which will in turn invoke the ValidateContacts method. We now however wish to open this up so that the ValidateContacts method is also visible to the MyProject.UnitTests library but NOT MyProject.UI.

First things first, as I am using signed assemblies I will need the full public key for my business assembly, this can be obtained by opening the visual studio command line and typing the following command:-

sn -Tp "C:\My Projects\MyProject.Business\Bin\MyProject.Business.dll"

This returns the following public key for the assembly:-


We now add the following InternalsVisibleTo attribute to the AssemblyInfo.cs fle  (located within the properties folder of the MyProject.Business projects) . If your assemblies are unsigned the public key is not required at all.

[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
[assembly: InternalsVisibleTo("MyProject.UnitTests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100d3485b9bbad933c83462d897d9121bc93c091c396c6f080a53c8812c1855a170038014b21ab10152583a8fe08c2ea2e5919af8078e97ada5c54f0f403dcb491da323623ad4340a294862d10440b0ab25746eea9311f0f9b5e2dd7c849ca1135bb65225131d959a10737c44639303c27e775771d7a4e523f32d14ae319041acc9")]

Note that we are giving the MyProject.UnitTests project (in its entirety) access to all methods and classes marked as internal residing within the MyProject.Business assembly. All private and protected methods are of course unaffected and behave in the same manner. With this in place I can now test the validation methods in isolation allowing us to increase and better target our unit testing meaning that our products can be more thoroughly tested before they even leave the development workbench.