What order are the Junit @Before/@After called?
I have an Integration Test Suite. I have a IntegrationTestBase
class for all my tests to extend. This base class has a @Before
(public void setUp()
) and @After
(public void tearDown()
) method to establish API and DB connections. What I've been doing is just overriding those two methods in each testcase and calling super.setUp()
and super.tearDown()
. However this can cause problems if someone forgets to call the super or puts them at the wrong place and an exception is thrown and they forget to call super in the finally or something.
What I want to do is make the setUp
and tearDown
methods on the base class final
and then just add our own annotated @Before
and @After
methods. Doing some initial tests it appears to always call in this order:
Base @Before
Test @Before
Test
Test @After
Base @After
but I'm just a little concerned that the order isn't guaranteed and that it could cause problems. I looked around and haven't seen anything on the subject. Does anyone know if I can do that and not have any problems?
Code:
public class IntegrationTestBase {
@Before
public final void setUp() { *always called 1st?* }
@After
public final void tearDown() { *always called last?* }
}
public class MyTest extends IntegrationTestBase {
@Before
public final void before() { *always called 2nd?* }
@Test
public void test() { *always called 3rd?* }
@After
public final void after() { *always called 4th?* }
}
Yes, this behaviour is guaranteed:
@Before
:
The
@Before
methods of superclasses will be run before those of the current class, unless they are overridden in the current class. No other ordering is defined.
@After
:
The
@After
methods declared in superclasses will be run after those of the current class, unless they are overridden in the current class.
One potential gotcha that has bitten me before:
I like to have at most one @Before
method in each test class, because order of running the @Before
methods defined within a class is not guaranteed. Typically, I will call such a method setUpTest()
.
But, although @Before
is documented as The @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
, this only applies if each method marked with @Before
has a unique name in the class hierarchy.
For example, I had the following:
public class AbstractFooTest {
@Before
public void setUpTest() {
...
}
}
public void FooTest extends AbstractFooTest {
@Before
public void setUpTest() {
...
}
}
I expected AbstractFooTest.setUpTest()
to run before FooTest.setUpTest()
, but only FooTest.setupTest()
was executed. AbstractFooTest.setUpTest()
was not called at all.
The code must be modified as follows to work:
public void FooTest extends AbstractFooTest {
@Before
public void setUpTest() {
super.setUpTest();
...
}
}
I think based on the documentation of the @Before
and @After
the right conclusion is to give the methods unique names. I use the following pattern in my tests:
public abstract class AbstractBaseTest {
@Before
public final void baseSetUp() { // or any other meaningful name
System.out.println("AbstractBaseTest.setUp");
}
@After
public final void baseTearDown() { // or any other meaningful name
System.out.println("AbstractBaseTest.tearDown");
}
}
and
public class Test extends AbstractBaseTest {
@Before
public void setUp() {
System.out.println("Test.setUp");
}
@After
public void tearDown() {
System.out.println("Test.tearDown");
}
@Test
public void test1() throws Exception {
System.out.println("test1");
}
@Test
public void test2() throws Exception {
System.out.println("test2");
}
}
give as a result
AbstractBaseTest.setUp
Test.setUp
test1
Test.tearDown
AbstractBaseTest.tearDown
AbstractBaseTest.setUp
Test.setUp
test2
Test.tearDown
AbstractBaseTest.tearDown
Advantage of this approach: Users of the AbstractBaseTest
class cannot override the setUp
/tearDown
methods by accident. If they want to, they need to know the exact name and can do it.
(Minor) disadvantage of this approach: Users cannot see that there are things happening before or after their setUp
/tearDown
. They need to know that these things are provided by the abstract class. But I assume that's the reason why they use the abstract class