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
connectionis 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
@BeforeAllonly for shared setup. - Use
@AfterAllto release resources created in@BeforeAll. - Avoid modifying the shared state between tests unless you reset it properly.
- Prefer
@BeforeEachwhen each test needs a fresh object. - By default, make
@BeforeAlland@AfterAllmethodsstatic. - 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 |
