How do I use @BeforeEach and @AfterEach in JUnit?

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
}