Advantages of Interfaces in Unit Testing

As a software developer I strive to integrate Unit Testing into my development process. At my organization there is a hard and fast rule, no testing code can reside in the production assembly. This was a problem with a class I was attempting to test because the class contains many protected methods that I wanted to be able to test in addition to the public interface to the class. Fortunately in .NET, if protected methods implement an interface on a class, you can access those methods if you create an object instance which is typed to the interface instead of the concrete class.

In C# you might do the following:


// This would be the class you are attempting to test in another assembly
public class Testing:ITestable {
protected Boolean TestThis() {return false;}

// You must make this interface public in order to execute the tests.
// However, if you only want to make this available in certain build
// configurations then you can easily add pre-compiler directives to
// exclude this interface from the release build configuration.

#if DEBUG
public Interface ITestable {
#else
private Interface ITestable {
#endif
Boolean TestThis();
}
}

//This class would reside in another class library assembly and get executing using an NUnit test runner.
[TestFixture()]
public class TestingTests {

[Test()]
public void TestThisTest() {
Testing.ITestable testObject = new Testing();

Assert.IsFalse(testObject.TestThis());
}
}


Essentially what is happening is that you conditionally include an interface which the unit testing class uses to reach inside of the object under test to enable testing of internal functions. One caveat, it is generally a much better design principle to just test the public interface, allowing for redesign and application of test cases to children who may inherit from the base class. However, for situations where you can not change the entire architecture, this method allows you to improve the code coverage of unit tests for classes with protected or private members that need testing.