Question

I have an interface, e.g.:

public interface Thing {
  FrobResult frob(FrobInput); 
}

And several implementations of that interface (e.g. NormalThing, ImmutableThing, AsyncThing) that I am trying to test.

Many of my test methods are really about ensuring that the interface is implemented correctly, and thus are duplicated across each Thing implementation. In JUnit 3 a common solution to this would be to create a base class (extending TestCase) that is then subclassed by each implementation class. But is this the correct approach for JUnit 4?

Possible alternatives in (I believe) ascending order of preference:

  1. Cut'n'paste the duplicated test methods. Not DRY at all, but I guess less worrisome in tests than it would be in production code.

  2. Create an abstract class with @Test methods, and subclass it for each implementation test class. (Commonly seen with JUnit 3 tests -- is this still a good way to go in JUnit 4?)

  3. Put the common test methods into a helper class, and invoke it on each implementation. (Composition instead of inheritance.)

What's the best practice for doing #3? Maybe a @RunWith(Parameterized.class) test that is parameterized with each implementation? Or is there a better way to accomplish this?

Was it helpful?

Solution

Yes, it is the correct approach to create a base class that is then subclassed by each implementation class in JUnit4, too.

I prefer the base test class for the interface to be abstract, i.e. your "alternative" 2, since I have made good experience in mimicing the inheritance hierarchy from the production code for the test code. So if you have interface I and implementations S1, S2 and S3, you make the abstract test class TestI and the test classes TestS1, TestS2 and TestS3.

Test cases should be speaking, i.e. tell a story. By choosing -- as always -- method names carefully and use clean behavioral subtyping only, inheritance does not obfuscate this.

OTHER TIPS

I use #2 approach for JUnit and TestNG test cases. This is most convenient and easy to maintain. Its also straight forward to pick up (since its native to OOD to have base class that has common methods). To me unit test classes are no different than regular project classes...so I do apply similar design considerations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top