What order are the Junit @Before/@After called?
Asked Answered
A

6

147

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?* }
}
Anastrophe answered 20/5, 2011 at 19:13 Comment(0)
J
153

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.

Janenejanenna answered 20/5, 2011 at 19:24 Comment(6)
To be clear, the order-of-execution of all the @Before methods is not guaranteed. If there are 10 @Before methods, each of them can be executed in any order; just before any other method.Frenchy
So instead of quoting the somewhat ambiguous documentation, can you please explain it in your own words? Are @Before and @After methods run before every other class method (once per method), or just before and after the entire suite of class methods (once per class) ?Constitutionality
See the important catch stated by John Q Citizen: "this only applies if each method marked with @Before has a unique name in the class hierarchy" Very important to remember!Hallow
I had a name conflict using the same method name on a @Before(d) method in a class and another method in its super class, on junit-4.12.Condemn
Does this rule also apply to @BeforeExample methods of ConcordionRunner?Abixah
According to invokeMethods in FixtureInstance.java it looks like parent-class methods are called before sub-class methods for both @BeforeExample and @AfterExample (and all the other Concordion annotated methods)Abixah
E
59

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();
    ...
  }
}
Edington answered 20/6, 2013 at 0:51 Comment(5)
Why not just change the name of the @Before method in the base class? This will save you from having to call to super in all the children...anyway good catch with the same names issueShiri
Just a remark to make things more secure: To avoid name clashes you can make the @Before/@After method(s) in the base class final, so the compiler will complain if you (accidentally) try to override them in the subclass.Marleah
The parent method of the same name not being run does not sound like a JUnit behavior. That sounds like how basic over-riding works in OOP. The parent method basically does not exist at run time. The child replaces it for all intents and purposes. That is how Java works.Freddyfredek
Another gotcha is that the parent classes have to be public, otherwise their @Before marked methods will be ignored if a subclass also has a @Before method.Bushtit
This is now documented behavior. "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" This allows having @Before mixin interfaces, but also preventing them from execution if an Override is givenPga
B
26

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

Blavatsky answered 9/7, 2013 at 13:58 Comment(2)
nice example - would be even more illustrative if you had two @Test methods, so it can be seen that setUp and tearDown wrap each test method.Crichton
I think this is the basis for the best answer to the OP, but you should fill in your answer to standalone. Could you augment your example to cover the alternatives others have suggested, as well, and explain why your proposal is superior?Izettaizhevsk
K
2

If you turn things around, you can declare your base class abstract, and have descendants declare setUp and tearDown methods (without annotations) that are called in the base class' annotated setUp and tearDown methods.

Kioto answered 20/5, 2011 at 19:21 Comment(1)
not a bad idea, but I don't want to enforce a contract on the tests that don't need their own setUp/tearDownAnastrophe
F
2

You can use @BeforeClass annotation to assure that setup() is always called first. Similarly, you can use @AfterClass annotation to assure that tearDown() is always called last.

This is usually not recommended, but it is supported.

It's not exactly what you want - but it'll essentially keep your DB connection open the entire time your tests are running, and then close it once and for all at the end.

Frenchy answered 20/5, 2011 at 19:26 Comment(3)
Actually, if you were to do this, I'd recommend creating a method setupDB() and closeDB() and marking them with @BeforeClass and @AfterClass and replacing your before/after methods with setup() and tearDown()Frenchy
Methods annotated with @BeforeClass and @AfterClass need to be static. What about the case, when we want to use instance variables inside these methods?Kiel
A warning when using @BeforeClass with Powermock: it only works for the first test run. See this issue: github.com/powermock/powermock/issues/398Fractocumulus
P
2

This isn't an answer to the tagline question, but it is an answer to the problems mentioned in the body of the question. Instead of using @Before or @After, look into using @org.junit.Rule because it gives you more flexibility. ExternalResource (as of 4.7) is the rule you will be most interested in if you are managing connections. Also, If you want guaranteed execution order of your rules use a RuleChain (as of 4.10). I believe all of these were available when this question was asked. Code example below is copied from ExternalResource's javadocs.

 public static class UsesExternalResource {
  Server myServer= new Server();

  @Rule
  public ExternalResource resource= new ExternalResource() {
      @Override
      protected void before() throws Throwable {
          myServer.connect();
         };

      @Override
      protected void after() {
          myServer.disconnect();
         };
     };

  @Test
  public void testFoo() {
      new Client().run(myServer);
     }
 }
Prosenchyma answered 2/11, 2015 at 1:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.