I was chatting to a coworker recently who was complaining about the way
setUp
works in JUnit, and more specifically, how fragile the "call super"
pattern is.

A lot of frameworks based on JUnit add their own initialization code, and not
only do they need to remember to invoke their parent’s setUp method,
you, as a user, need to remember to invoke theirs after you wrote your
initialization code:

Third party:

public class DBUnitTestCase extends TestCase {
  public void setUp() {
    super.setUp();
    // do my own initialization
  }

Client code:

public class DBTestCase extends DBUnitTestCase {
  public void setUp() {
    super.setUp();  // initialize DBUnit, which will
initialize JUnit
    // my own initialization
  }
}

Of course, you need to remember to apply this pattern with tearDown()
as well, except…  in the reverse order.

There are a few problems with this approach, but two of them really strike me
as potentially very dangerous:

  • If you forget to call super, you are breaking everything (and
    in obscure ways).  Of course, IDE’s can help you with that by providing
    templates for these methods, but there’s no standard way of doing this and
    no enforcement from the JVM.
     
  • In the chain of command, what happens if a call to setUp()
    fails or throws an exception?  And is the corresponding tearDown()
    method invoked?  Even partially?

These are two very difficult problems, and actually, I don’t really have a
solution for the latter one.  However, the super anti-pattern can
be remedied quite easily.

I am actually shocked that JUnit forces you to use this anti-pattern, while
it would have been so easy to avoid it and be more symmetric in its
usage.  Basically, here is what I don’t like:

How come your test methods need to follow a certain naming pattern in
order to be picked up by JUnit, but the rule is different for setUp/tearDown?

Wouldn’t it be nice if I could have any arbitrary number of setUp()
methods and all they need to do is start with the name "setUp"?

Suddenly, all the problems mentioned above disappear:

  • No need to call super.  JUnit walks through all the test classes,
    consider any method that starts with "setUp" as a per-method
    initialization method, and then moves on to the next test class (and/or
    parent class).
     
  • Now I can have several setUp() methods (not the most useful
    thing, but why the silly restriction to one method anyway?).

Basically, instead of reusing and hijacking a fundamental mechanism of Java
(inheritance), just give freedom to users and implement your own mechanism.

Of course, an even cleaner way to do this (which you can find in
TestNG :-)) is to go one step further: 
relax the naming restriction on your methods and use annotations to tag them.