1. Introduction
In this short tutorial, we’re going to explain the differences between the @Before, @BeforeClass, @BeforeEach and @BeforeAll annotations in JUnit 4 and 5 – with practical examples of how to use them.
We’ll also cover briefly their @After complementary annotations.
Let’s start with JUnit 4.
2. @Before
Methods annotated with the @Before annotation are executed before each test. This is useful when we want to execute some common code before running a test.
Let’s see an example where we initialize a list and add some values:
@RunWith(JUnit4.class) public class BeforeAndAfterAnnotationsTest { // ... private List<String> list; @Before public void init() { LOG.info("startup"); list = new ArrayList<>(Arrays.asList("test1", "test2")); } @After public void finalize() { LOG.info("finalize"); list.clear(); } }
Notice that we also added another method annotated with @After in order to clear the list after the execution of each test.
After that, let’s add some tests to check the size of our list:
@Test public void whenCheckingListSize_thenSizeEqualsToInit() { LOG.info("executing test"); assertEquals(2, list.size()); list.add("another test"); } @Test public void whenCheckingListSizeAgain_thenSizeEqualsToInit() { LOG.info("executing another test"); assertEquals(2, list.size()); list.add("yet another test"); }
In this case, it’s crucial to make sure that test environment is properly set up before running each test since the list is modified during every test execution.
If we take a look at the log output we can check that the init and finalize methods were executed once per test:
... startup ... executing another test ... finalize ... startup ... executing test ... finalize
3. @BeforeClass
When we want to execute an expensive common operation before each test, it’s preferable to execute it only once before running all tests using @BeforeClass. Some examples of common expensive operations are the creation of a database connection or the startup of a server.
Let’s create a simple test class that simulates the creation of a database connection:
@RunWith(JUnit4.class) public class BeforeClassAndAfterClassAnnotationsTest { // ... @BeforeClass public static void setup() { LOG.info("startup - creating DB connection"); } @AfterClass public static void tearDown() { LOG.info("closing DB connection"); } }
Notice that these methods have to be static, so they’ll be executed before running the tests of the class.
As we did before, let’s also add some simple tests:
@Test public void simpleTest() { LOG.info("simple test"); } @Test public void anotherSimpleTest() { LOG.info("another simple test"); }
This time, if we take a look at the log output we can check that the setup and tearDown methods were executed only once:
... startup - creating DB connection ... simple test ... another simple test ... closing DB connection
4. @BeforeEach and @BeforeAll
@BeforeEach and @BeforeAll are the JUnit 5 equivalents of @Before and @BeforeClass. These annotations were renamed with clearer names to avoid confusion.
Let’s duplicate our previous classes using these new annotations, starting with the @BeforeEach and @AfterEach annotations:
@RunWith(JUnitPlatform.class) class BeforeEachAndAfterEachAnnotationsTest { // ... private List<String> list; @BeforeEach void init() { LOG.info("startup"); list = new ArrayList<>(Arrays.asList("test1", "test2")); } @AfterEach void finalize() { LOG.info("finalize"); list.clear(); } // ... }
If we check logs, we can confirm that it works in the same way as with the @Before and @After annotations:
... startup ... executing another test ... finalize ... startup ... executing test ... finalize
Finally, let’s do the same with the other test class to see the @BeforeAll and @AfterAll annotations in action:
@RunWith(JUnitPlatform.class) public class BeforeAllAndAfterAllAnnotationsTest { // ... @BeforeAll public static void setup() { LOG.info("startup - creating DB connection"); } @AfterAll public static void tearDown() { LOG.info("closing DB connection"); } // ... }
And the output is the same as with the old annotation:
... startup - creating DB connection ... simple test ... another simple test ... closing DB connection
5. Conclusion
In this article, we showed the differences between the @Before, @BeforeClass, @BeforeEach and @BeforeAll annotations in JUnit and when each of them should be used.
As always, the full source code of the examples is available over on GitHub.