Unit testing internals

Posted by Chris on October 04, 2006

One of the cool things about Dotway is that we have these “competence weekends” three or four times a year, where we go away to some hotel and geek out about something more or less of technical nature. As “AndrĂ©s”:http://www.taylor.se/blog/ mentions recently we spent a weekend “learning about TDD”:http://www.taylor.se/blog/2005/11/24/talking-about-agile/. One of the things that we discussed was how to test code that is not public. Normally you place your tests in a separate assembly and reference the production code. However, that means you need to make types and members public to be able to test them. So if you want to keep the implementation details hidden (with internal access level) you will need to have the tests in the same assembly as the production code. That brings further challenges in setting up the build environment to create different builds, since you naturally do not want to include the tests in the released code.

Today I stumbled upon a .NET 2.0 feature that helps solve this. I was setting up an assembly with attributes and noted one I had not seen before:

@InternalsVisibleToAttribute (string assemblyName)@

That sounded like something interesting, so I decided to try it. I created a new solution and added a class library project called Code to it. I then added a second class library that I named Tests, which referenced Code (and NUnit.Framework). In the AssemblyInfo.cs for Code I added the following:

@[assembly: InternalsVisibleTo("Tests")]@

Now I was ready to start testing. In Code I created two classes, publicclass.cs and internalclass.cs as shown below.

// publicclass.cs
namespace Code {
  public class publicclass {
    internal bool internalmethod() {
      return true;
    }
    public bool publicmethod() {
      return true;
    }
  }
}

// internalclass.cs
namespace Code {
  internal class internalclass {
    public bool publicmethod() {
      return true;
    }

    internal bool internalmethod() {
      return true;
    }
  }
}

In the Tests project I then added InternalsVisibleToTests.cs, shown below:

// InternalsVisibleToTests.cs
using NUnit.Framework;
namespace Tests {
  [TestFixture]
  public class InteralsVisibleToTests {
    [Test]
    public void AccessPublicClassMembers() {
      Code.publicclass foo = new Code.publicclass();
      bool condition1 = foo.publicmethod();
      bool condition2 = foo.internalmethod();

      Assert.IsTrue(condition1);
      Assert.IsTrue(condition2);
    }

    [Test]
    public void AccessInternalClassMembers() {
      Code.internalclass foo = new Code.internalclass();
      bool condition1 = foo.publicmethod();
      bool condition2 = foo.internalmethod();

      Assert.IsTrue(condition1);
      Assert.IsTrue(condition2);
    }
  }
}

As you can see these tests refer to both internal types and members in the Code assembly. The solution compiles and the tests are green!

Even though my libraries often do not need this (most of the stuff is public anyway), it is a very useful technique to have access to. It should be noted of course that this means that anyone can create an assembly named Tests and access the internals in my Code assembly, but there are of course ways around that.

Trackbacks

Trackbacks are closed.

blog comments powered by Disqus