How do I use @BeforeAll and @AfterAll in JUnit?

In JUnit 5, @BeforeAll and @AfterAll are lifecycle annotations used to run setup and cleanup code once per test class.

They are useful when you need to initialize or clean up expensive shared resources, such as:

  • database connections
  • test containers
  • temporary directories
  • mock servers
  • shared test data
  • application-wide configuration

Basic Rule

By default, methods annotated with @BeforeAll and @AfterAll must be static.

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class ExampleTest {

    @BeforeAll
    static void setUpBeforeAllTests() {
        System.out.println("Runs once before all tests");
    }

    @AfterAll
    static void cleanUpAfterAllTests() {
        System.out.println("Runs once after all tests");
    }

    @Test
    void firstTest() {
        System.out.println("First test");
    }

    @Test
    void secondTest() {
        System.out.println("Second test");
    }
}

Execution order:

Runs once before all tests
First test
Second test
Runs once after all tests

Compared with @BeforeEach and @AfterEach

@BeforeAll and @AfterAll run once for the whole test class.

@BeforeEach and @AfterEach run before and after every test method.

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class LifecycleTest {

    @BeforeAll
    static void beforeAll() {
        System.out.println("Before all tests");
    }

    @BeforeEach
    void beforeEach() {
        System.out.println("Before each test");
    }

    @Test
    void testOne() {
        System.out.println("Test one");
    }

    @Test
    void testTwo() {
        System.out.println("Test two");
    }

    @AfterEach
    void afterEach() {
        System.out.println("After each test");
    }

    @AfterAll
    static void afterAll() {
        System.out.println("After all tests");
    }
}

Output will be similar to:

Before all tests
Before each test
Test one
After each test
Before each test
Test two
After each test
After all tests

Practical Example

Suppose several tests need the same expensive resource.

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

class DatabaseConnectionTest {

    private static FakeDatabaseConnection connection;

    @BeforeAll
    static void openConnection() {
        connection = new FakeDatabaseConnection();
        connection.open();
    }

    @AfterAll
    static void closeConnection() {
        connection.close();
    }

    @Test
    void connectionShouldBeOpen() {
        assertTrue(connection.isOpen());
    }

    @Test
    void canExecuteQuery() {
        assertTrue(connection.execute("SELECT 1"));
    }
}

Here:

  • openConnection() runs once before all tests.
  • The same connection is reused by all test methods.
  • closeConnection() runs once after all tests finish.

Using Non-Static @BeforeAll and @AfterAll

If you do not want these methods to be static, annotate the test class with:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)

Example:

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class NonStaticLifecycleTest {

    private String sharedValue;

    @BeforeAll
    void beforeAll() {
        sharedValue = "ready";
    }

    @AfterAll
    void afterAll() {
        sharedValue = null;
    }

    @Test
    void testSharedValue() {
        assert sharedValue.equals("ready");
    }
}

With PER_CLASS, JUnit creates one instance of the test class and reuses it for all test methods. Because of that, @BeforeAll and @AfterAll can be instance methods.

When Should You Use Them?

Use @BeforeAll for setup that should happen once, such as:

@BeforeAll
static void startServer() {
    // start shared server
}

Use @AfterAll for cleanup that should happen once, such as:

@AfterAll
static void stopServer() {
    // stop shared server
}

Avoid using them for the per-test state. For that, prefer @BeforeEach.

Important Best Practices

  • Use @BeforeAll only for shared setup.
  • Use @AfterAll to release resources created in @BeforeAll.
  • Avoid modifying the shared state between tests unless you reset it properly.
  • Prefer @BeforeEach when each test needs a fresh object.
  • By default, make @BeforeAll and @AfterAll methods static.
  • Use @TestInstance(TestInstance.Lifecycle.PER_CLASS) only when you specifically want non-static lifecycle methods.

In short:

Annotation Runs When? Usually Static?
@BeforeAll Once before all tests Yes
@AfterAll Once after all tests Yes
@BeforeEach Before each test method No
@AfterEach After each test method No

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.