Junit5 Test Lifecycle @BeforeAll @BeforeEach @AfterAll @AfterEach
|In this article, we will discuss the lifecycle of a Test in JUnit5, what all the important annotations are, their meaning, and how we can use them to write unit tests.
1. Annotations
Note– When we use the term ‘test method’ in the following headings it refers to all the methods annotated with @Test
, @RepeatedTest
, @ParameterizedTest
, or @TestFactory
2. @Test
This annotation marks a method as a test method. There are other annotations as well like @RepeatedTest, @ParameterizedTest, or @TestFactory in case we want additional functionality.
In JUnit5 this annotation does not accept any arguments.
Let see how test methods look like
@Test void testMethod() { System.out.println("@Test method executed"); } @ParameterizedTest @ValueSource(ints = {1,2}) void testParameterizedMethod(int number) { System.out.println("@ParameterizedTest executed with number " + number); } @RepeatedTest(2) void repeatedTestExample() { System.out.println("@RepeatedTest"); }
3. @BeforeEach
This method is executed before each test method. This is used to ensure we have clean data(for eg. setting up mocks) for each test case and is not updated by any other already executed @Test method.
Let see how @BeforeEach method look like
@BeforeEach void runBeforeEveryTest() { System.out.println("@BeforeEach executed"); }
4. @AfterEach
This method is executed after each test method. This is generally used to clean up the data or to perform an action after a @Test method.
If it is just a cleanup of data then sometimes it is can also be done in @BeforeEach
method.
Let see how @AfterEach method look like
@AfterEach void runAfterEveryTest() { System.out.println("@AfterEach executed \n"); }
5. @BeforeAll
@BeforeAll runs only once before all the test methods of a Test class.
Sometimes there are heavy operations like setting up a Database connection or spinning up an embedded server etc which should be done only once for a test class.
Let see how @BeforeAll method look like
@BeforeAll static void runOnceBeforeAllTests() { System.out.println("@BeforeAll executed \n"); }
6. @AfterAll
@AfterAll runs only once after all the test methods of a Test class.
Mostly the setup that is done in @BeforeAll method also needs to be cleaned up like closing the Database connection or shutting down the embedded server etc which is generally done only once for a test class.
Let see how @AfterAll method look like
@AfterAll static void runOnceAfterAllTests() { System.out.println("@AfterAll executed"); }
7. JUnit5 test lifecycle Sample
So let’s go through a full sample and see how all the annotations we have discussed above run and in which order
package com.codingeek; import org.junit.jupiter.api.*; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import java.util.function.Function; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; class LifecycleSampleTest { @BeforeAll static void runOnceBeforeAllTests() { System.out.println("@BeforeAll executed \n"); } @BeforeEach void runBeforeEveryTest() { System.out.println("@BeforeEach executed"); } @Test void testMethod() { System.out.println("@Test method executed"); } @ParameterizedTest @ValueSource(ints = {1, 2}) void testParameterizedMethod(int number) { System.out.println("@ParameterizedTest executed with number " + number); } @RepeatedTest(2) void repeatedTestExample() { System.out.println("@RepeatedTest"); } @AfterEach void runAfterEveryTest() { System.out.println("@AfterEach executed \n"); } @AfterAll static void runOnceAfterAllTests() { System.out.println("@AfterAll executed"); } }
In the following output we how @BeforeEach and @AfterEach is related to an execution of a test method and @BeforeAll and @AfterAll is related to the execution of a test class
Output:- @BeforeAll executed @BeforeEach executed @RepeatedTest @AfterEach executed @BeforeEach executed @RepeatedTest @AfterEach executed @BeforeEach executed @ParameterizedTest executed with number 1 @AfterEach executed @BeforeEach executed @ParameterizedTest executed with number 2 @AfterEach executed @BeforeEach executed @Test method executed @AfterEach executed @AfterAll executed
8. JUnit4 @BeforeClass and @Before
@BeforeClass and @Before annotation until JUnit4 are the same as @BeforeAll and @BeforeEach from JUnit5. These annotations are renamed to have clear naming and to avoid ambiguity.
Let’s rewrite the methods written above to use the JUnit4 annotations.
//@BeforeEach @Before void runBeforeEveryTest() { System.out.println("@Before executed"); } //@BeforeAll @BeforeClass static void runOnceBeforeAllTests() { System.out.println("@BeforeClass executed \n"); }
9. JUnit4 @AfterClass and @After
Similar to the previous ones @AfterClass and @After annotation until JUnit4 are the same as @AfterAll and @AfterEach from JUnit5.
Let’s rewrite the methods written above to use the JUnit4 annotations.
//@AfterEach @After void runAfterEveryTest() { System.out.println("@After executed \n"); } //@AfterAll @AfterClass static void runOnceAfterAllTests() { System.out.println("@AfterClass executed"); }
10. Conclusion
In this JUnit 5 tutorial, we have learned that by using some of the basic annotations @Test, @BeforeEach, @AfterEach, @BeforeAll, @AfterAll we can cover the basic test requirements.
We also learned how JUnit5 annotations are different from JUnit4 annotations like @AfterClass, @After, @BeforeClass, and @Before.
Complete code samples are present on Github project.
An investment in knowledge always pays the best interest. I hope you like the tutorial. Do come back for more because learning paves way for a better understanding
Do not forget to share and Subscribe.
Happy coding!! ?