Reputation:
Usually, I only have one implementation of an interface in my application and that first implementation is always used when writing the tests for the interface. Let's say I have an interface Destroyer
and an implementation DestroyerImpl
. Then I would use that class in the test:
class DestroyerTest
{
private Destroyer destroyer = new DestroyerImpl();
@Test
public void test() { ... }
}
The class is then implicitly tested by being instantiated in the testing of the interface.
If I write another implementation class EpicDestroyer
I now feel like I have to test that as well.
So, do I write two test classes DestroyerImplTest
and EpicDestroyerTest
that both test the same Destroyer
interface with different implementations? Wouldn't that be redundant? I could test each implementation in the same test suite by parameterizing it. Is this the way to do it?
Upvotes: 2
Views: 944
Reputation: 13556
I think there is a misconception in your thinking about testing.
There is no sense in testing an interface as it is only a specification. Only implementations can be tested. So you should test all implementations. However you may be able to derive test cases from the interface as all implementations need to adhere to the specifications in there. So even though you have completely different implementations you may share tests between those.
In my mind there should be test classes like the following:
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public abstract class AbstractModifiableListTest
{
protected abstract <T> List<T> createListInstanceUnderTest(T... elements);
@Test
public void removeDecreasesSizeByOne() {
List<String> list = this.<String>createListInstanceUnderTest("a","b","c");
int originalSize = list.size();
list.remove( 0 );
int newSize = list.size();
Assert.assertEquals( originalSize - 1, newSize );
}
}
that contain the test cases that test the specification of the interface - java.util.List
in this case. Tests for Implementations then parameterize the test case by implementing abstract methods and possibly adding implementation dependent test cases.
Upvotes: 6
Reputation: 62864
I wouldn't say that interfaces can be tested, because they provide abstraction and not implementation. Tests, on the other hand, need to ensure if a specific behavior is implemented (and the behavior is in the classes).
So, do I write two test classes DestroyerImplTest and EpicDestroyerTest that both test the same Destroyer interface with different implementations?
I would say, yes.
Upvotes: 3
Reputation: 411
I never "test" an interface because there is nothing to test. The interface describe the service each implentation as to deliver, Its the contract.
So you have to test each implementation of this service to ensure everybody does the job correctly.
Upvotes: 2
Reputation: 393916
If you are testing the interface, it should be sufficient to test it with a single implementation, since the interface doesn't depend on a specific implementation.
Of course you'll probably want to test each implementation, but for the purpose of testing the implementing class, not the interface itself.
Upvotes: 1