In JUnit 5, @BeforeEach and @AfterEach are lifecycle annotations.
They let you run code before and after every test method.
| Annotation | When it runs | Common use |
|---|---|---|
@BeforeEach |
Before each @Test method |
Create objects, initialize test data, reset state |
@AfterEach |
After each @Test method |
Clean up resources, close files/connections, reset temporary state |
Basic Example
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator();
}
@AfterEach
void tearDown() {
calculator = null;
}
@Test
void addReturnsSumOfTwoNumbers() {
int result = calculator.add(2, 3);
assertEquals(5, result);
}
@Test
void subtractReturnsDifferenceOfTwoNumbers() {
int result = calculator.subtract(10, 4);
assertEquals(6, result);
}
}
Here is the execution order:
setUp()
addReturnsSumOfTwoNumbers()
tearDown()
setUp()
subtractReturnsDifferenceOfTwoNumbers()
tearDown()
So each test gets a fresh setup.
What @BeforeEach Is For
Use @BeforeEach when several tests need the same preparation.
For example:
@BeforeEach
void setUp() {
calculator = new Calculator();
}
This avoids repeating the same setup code in every test:
@Test
void addReturnsSumOfTwoNumbers() {
calculator = new Calculator();
assertEquals(5, calculator.add(2, 3));
}
Instead, the test can focus only on the behavior being tested:
@Test
void addReturnsSumOfTwoNumbers() {
assertEquals(5, calculator.add(2, 3));
}
What @AfterEach Is For
Use @AfterEach when you need cleanup after every test.
Common examples include:
- Closing files
- Closing database connections
- Deleting temporary files
- Clearing test data
- Resetting shared state
Example:
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ShoppingCartTest {
private List<String> cart;
@BeforeEach
void setUp() {
cart = new ArrayList<>();
}
@AfterEach
void tearDown() {
cart.clear();
}
@Test
void cartStartsEmpty() {
assertEquals(0, cart.size());
}
@Test
void itemCanBeAddedToCart() {
cart.add("Book");
assertEquals(1, cart.size());
}
}
Method Names Are Flexible
The method names do not have to be setUp() and tearDown().
These are common names, but any valid method name works:
@BeforeEach
void createTestObjects() {
// setup code
}
@AfterEach
void cleanUpTestObjects() {
// cleanup code
}
JUnit cares about the annotations, not the method names.
Important Rules
In JUnit 5:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
The lifecycle methods should usually be:
@BeforeEach
void setUp() {
}
and:
@AfterEach
void tearDown() {
}
They are typically:
- Not
static - Package-private or public
- Return
void - No parameters, unless using advanced JUnit features such as dependency injection
@BeforeEach vs @BeforeAll
Do not confuse @BeforeEach with @BeforeAll.
| Annotation | Runs |
|---|---|
@BeforeEach |
Before every test method |
@BeforeAll |
Once before all tests in the class |
Example:
@BeforeAll
@BeforeEach
@Test
@AfterEach
@BeforeEach
@Test
@AfterEach
@AfterAll
Use @BeforeEach when each test should start with a clean, fresh setup.
Use @BeforeAll for expensive setup that only needs to happen once.
Complete Example
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class BankAccountTest {
private BankAccount account;
@BeforeEach
void setUp() {
account = new BankAccount(100);
}
@AfterEach
void tearDown() {
account = null;
}
@Test
void depositIncreasesBalance() {
account.deposit(50);
assertEquals(150, account.getBalance());
}
@Test
void withdrawDecreasesBalance() {
account.withdraw(30);
assertEquals(70, account.getBalance());
}
}
Each test starts with a new account balance of 100.
That means depositIncreasesBalance() does not affect withdrawDecreasesBalance().
Summary
Use:
@BeforeEach
to prepare a fresh test environment before every test.
Use:
@AfterEach
to clean up after every test.
A typical pattern is:
@BeforeEach
void setUp() {
// create test objects
}
@Test
void someTest() {
// run test
}
@AfterEach
void tearDown() {
// clean up
}
