2

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?

Community
  • 1
  • 1

4 Answers4

6

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.

SpaceTrucker
  • 13,377
  • 6
  • 60
  • 99
  • So basically you're saying there's no such thing as a `DestroyerTest`, only `DestroyerImplTest` and `SomeOtherDestroyerImplTest`? –  Oct 31 '14 at 09:57
  • @HermanTorjussen Correct, but there could be an `AbstractDestroyerTest` as an abstract test class for example that contains the unit tests that are shared between implementations. But that depends on how you do the parameterization of the unit test. – SpaceTrucker Oct 31 '14 at 10:13
3

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.

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • Could you give an example on how to reuse tests on different implementations? I would like to avoid writing the same test suite again for each new implementation of an interface. –  Oct 31 '14 at 09:44
  • @HermanTorjussen: why would you want to *reuse* them? If implementation is different it requires different tests. If it isn't it shouldn't even exist. – k.m Oct 31 '14 at 10:03
  • @HermanTorjussen, I deleted my last statement, because extending unit tests is actually considered as a bad practice. Checkout [this](http://www.petrikainulainen.net/programming/unit-testing/3-reasons-why-we-should-not-use-inheritance-in-our-tests/) article. – Konstantin Yovkov Oct 31 '14 at 10:04
2

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.

zeraDev
  • 381
  • 1
  • 3
  • 16
1

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.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • "since the interface doesn't depend on a specific implementation" - how would you "test an interface" without having some implementation class to test against? This makes no sense to me... – Gyro Gearless Oct 31 '14 at 09:35
  • @GyroGearless I'm saying you should test it against a single implementation, since the interface doesn't depend on any specific implementation. – Eran Oct 31 '14 at 09:37
  • @Eran, i agree with Gyro. Its quite confusiong to say "if you are testing...it should be sufficient..." You do not test an interface, that's it ;) – zeraDev Oct 31 '14 at 09:43