When I first started unit testing with NUnit (back with version 1.1 of .net),
I found that to get some of the lower level class functionality tested (for example 'internal' methods) I needed to do it from inside the project that I was testing.
I used the #if DEBUG directive to compile out the code from the release build but this quickly became messy (and also produced other issues).
Then I went through a phase where used a separate project and I made allot more of the class members and properties public than normal simply so that I could test things easily, for example by assigning mocked objects etc. The problem with that was people started getting confused with all the "extra" methods and properties.
Next, I reverted back to the standard private, protected and public class design and used the separate testing project just focusing on the public members (but again missing out on the lower level testing).
Just before I started to write some helper classes that used reflection to get access to these class members, I stumbled across the "InternalsVisibleTo(string assemblyName)" attribute.
Assume you have a project "App" containing the code you want to test, such as "Util.cs":
public class Util
{
public static ResultObject Foo()
{
// callable from external unit test assembly
// code...
int i = BaaOne();
// code...
string str = BaaTwo(i);
// code...
return result;
}
internal static int BaaOne()
{
// only available within App assembly
// code...
}
internal static string BaaTwo(int i)
{
// only available within App assembly
// code...
}
}
Normally you can only test the
Util.Foo method from the external unit test assembly.
// in App.UnitTest.dll
using System;
using NUnit.Framework;
namespace App.UnitTest
{
[TestFixture]
public class UtilTests
{
[Test(Description = "Test public method Util.Foo")]
public void Foo()
{
//... No access to App's internal methods
}
}
}
In the sample above Foo makes calls to BaaOne and BaaTwo, what if I want to test these methods too in an effort to make my testing more granular and help me locate issues in an easier manner etc?
Add this to the AssemblyInfo.cs file in the App project:
// in App.dll's AssemblyInfo.cs file
[assembly:InternalsVisibleTo("App.UnitTest")]
Declared at the assembly level with a class name, it signals the named assembly as a "friend" assembly that has access to the methods and properties of the defining assemblies' internal members. In the case above it means that App.UnitTest.dll now has access to not just the Foo method, but also the two internal methods, BaaOne and BaaTwo while keeping them hidden from other assemblies.
Now I can execute the following tests:
using System;
using NUnit.Framework;
namespace App.UnitTest
{
[TestFixture]
public class UtilTests
{
[Test(Description = "Test public method Util.Foo")]
public void Foo()
{
//...
}
[Test(Description = "Test internal method Util.BaaOne")]
public void BaaOne()
{
//...
}
[Test(Description = "Test internal method Util.BaaTwo")]
public void BaaTwo()
{
//...
}
}
}
Visual Basic .Net Note: Sorry - but you can't use this handy attribute until Orcas is out [:(]