In JUnit 5, lifecycle methods are special methods that manage tests’ setup and teardown process. They allow developers to perform tasks before and after each test or the entire test suite. This helps prepare the test environment and clean up resources afterwards. The process is driven through four primary annotations that are @BeforeAll, @BeforeEach, @AfterEach, and @AfterAll. We need to annotate each method with @Test annotation from the org.junit.jupiter.api package.
JUnit 5 manages test execution through a lifecycle that can be broken down into three phases: Setup, Test Execution and Cleanup.
Setup Phase
It is responsible for preparing the test environment before the actual test methods are executed. JUnit 5 provides two levels of Setup: class-level and method-level setup.
@BeforeAll
The class-level setup uses the @BeforeAll annotation which executes once before any test method in the class runs. It is useful for initializing resources that are expensive or time-consuming to create such as establishing database connections or starting external services. The @BeforeAll method must be declared as static.
@BeforeAll
static void setupClass()
{
// Code for class-level setup
}
@BeforeEach
It runs before each test method and its purpose is to setup resources or reset the state before each test method runs. This type of setup is useful for preparing or resetting test-specific objects and ensuring that each test runs in isolation with a clean state.
@BeforeEach
void setupMethod()
{
// Code for method-level setup
}
Test-Execution Phase
In this phase, the actual test methods are executed and assertions are performed to verify expected outcomes. Test methods are marked with the @Test annotation
@Test
void testMethod()
{
// Test logic and assertions
}
Cleanup Phase
This phase ensures that any resources initialized during the setup phase are properly cleaned up. It also offers class-level and method-level cleanup mechanisms.
@AfterAll
It executes once after all test methods have run and it is typically used for closing global resources such as database connections or stopping the servers.
@AfterAll
static void cleanupClass()
{
// Code for class-level cleanup
}
@AfterEach
The method level cleanup uses the @AfterEach annotation and runs after each test method. It is useful for resetting resources, cleaning the caches or deleting any temporary files to ensure that subsequent tests are unaffected by any changes that were made in previous tests.
@AfterEach
void cleanupMethod()
{
// Code for method-level cleanup
}
Now let’s see this in practical.
Follow the previous article for a better understanding of JUnit 5
- Create a Calculator class in src/main/java location.
2. Next, create a CalculatorTest class too see all the annotations in action.
package io.junit5.demo;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CalculatorTest {
@BeforeAll
static void setUpClass() {
System.out.println("Setting up class-level resources");
}
@BeforeEach
void setUpTest() {
System.out.println("Setting up method-level resources");
}
@Test
void testAddition() {
System.out.println("Running addition test");
Assertions.assertEquals(5, 2 + 3);
}
@Test
void testSubtraction() {
System.out.println("Running subtraction test");
Assertions.assertEquals(1, 3 - 2);
}
@AfterEach
void tearDownTest() {
System.out.println("Cleaning up method-level resources");
}
@AfterAll
static void tearDownClass() {
System.out.println("Cleaning up class-level resources");
}
}
3. Save the file and Run as a JUnit Test and check the output in the console.
This output reflects the execution order of the setup, test, and cleanup phases as defined by the @BeforeAll, @BeforeEach, @Test, @AfterEach and @AfterAll annotations in the JUnit 5 test lifecycle.
Similar Posts
Master JUnit 5: The Ultimate Guide to Java Testing
How To Build Your First JUnit5 Test Case