I am trying to write contract tests for some widely used interfaces:
Along the lines of:
public abstract class MyInterfaceContractTest extends TestCase {
private MyInterface _toTest;
public void setUp(){
_toTest = getTestableImplementation();
}
protected abstract MyInterface getTestableImplementation();
public void testContract(){
}
}
…and…
public class MyInterfaceImplementationTest extends MyInterfaceContractTest {
protected MyInterface getTestableImplementation(){
return new MyInterfaceImplementation(...);
}
}
However, I want to be able to test multiple instances of MyInterfaceImplementation. In my use case, this is an immutable object containing a collection of data (with accessors specified as per the interface MyInterface), and it might be empty, or have a small amount of data, or even lots of data.
So the question is, how can I test multiple instances of my implementations?
At the moment, I have to initialise the implementation to pass it into the abstract contract test. One approach would be to have multiple test classes for each implementation, where each test class tests a particular instance of that implementation – but that then seems a bit voluminous and difficult to keep track of.
FWIW, I’m using JUnit 3.
If I’ve understood your need correctly, you want to run the same test method or methods with multiple implementations of the same interface.
I don’t know how to do this very nicely in JUnit 3.
If you’re willing to upgrade to JUnit 4, this can be done by using a parametrized test.
For the simple example of running a single test method on two implementations of an interface, your test code could look something like this:
On running this test, JUnit will run the test twice, calling the constructor with the successive entries in the parameter list.
If you have more complex things, like different expectations for the different implementations, the data generation could return lists of Object arrays that contain multiple elements, and the constructor would then take a corresponding multiple arguments.
If you need to reinitialize the object under test between test methods, you might also want to use the trick I described in this related question.
I believe similar things are possible in TestNG, which might be another choice for your upgrade path.