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.