C# and NUnit – testing interface implementations
June 4, 2010 1 Comment
A common development strategy is to generate interface definitions and then code against these – allowing the implementations to be varied easily.
When writing NUnit test cases for interfaces and implementing classes – it is possible to generate a set of test cases for the interface and then apply these test cases to each concrete implementation. A strategy is outlined below.
Within the class library containing the test cases generate a test fixture for the interface itself. A class member, m_fileManager in this case, is used to hold the interface instance to test and a second member m_runTests is used to track whether the fixture holds an interface realisation.
A virtual function CreateConcrete is defined to create the concrete interface implementation – it is called in the SetUp method.
Add the interface test cases to this class – checking whether tests should by run using the m_runTests member.
[TestFixture]
public class Test_IFileManager
{
/// Interface to use for testing
protected IFileManager m_fileManager;
/// Indicator that we are in a realisation test fixture
protected bool m_runTests = false;
/// Create a concrete instance
virtual public void CreateConcrete()
{
}
[SetUp]
/// Test set up
public void Setup()
{
CreateConcrete();
}
[TearDown]
/// Test tear down
public void TearDown()
{
m_fileManager = null;
m_runTests = false;
}
[Test]
/// A simple test
public void NonExistentDirectoryThrowsException()
{
if (m_runTests)
{
Console.WriteLine("Running test: NonExistentDirectoryThrowsException");
Assert.Throws<DirectoryNotFoundException>
( delegate
{
m_fileManager.GetFreeFileName(@"ZZ:\BadDrive\", "stem", "txt");
});
}
}
}
To attach the set of test cases to a concrete implementation, generate a class that inherits this base interface testing class. Override the CreateConcrete method to assign the interface instance and to indicate that the tests should be run.
[TestFixture]
public class Test_IFileManager_SimpleFileManager : Test_IFileManager
{
/// Create a concrete instance
override public void CreateConcrete()
{
// Using static method
m_fileManager = (IFileManager) SimpleFileManager.GetFileManager();
m_runTests = true;
}
}
Each implementing class can be tested by creating a separate concrete implementation testing class. When NUnit runs it finds all of the interface tests and runs them for each concrete implementation.
If any implementation-specific test cases exist, then they can be added to the concrete testing class. If a class implements multiple interfaces, then each interface can be tested in a similar manner by generating a concrete implementation testing class for each interface / implementer pair.