By default, JUnit runs tests using a deterministic but unpredictable order (MethodSorters. DEFAULT). In most cases, that behavior is perfectly fine and acceptable. But there are cases when we need to enforce a specific ordering.
@Before and @After.
junit Getting started with junit @Before, @AfterThis can be used to repeatedly set up a Test setting and clean up after every test. So the tests are independent and preparation code is not copied inside the @Test method. Methods annotated with @Before or @After must be public void and with zero arguments.
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
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.
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.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With