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.
Nice idea – I’ve done something similar to this in the past. You can use parameterized test fixtures (in NUnit 2.5) so that you need only declare one test class, and then pass each concrete implementation in as a test fixture parameter. NUnit will instantiate and run the test class once for each parameter that you pass in. See http://nunit.org/index.php?p=testFixture&r=2.5.