Difference between @Before, @BeforeClass, @BeforeEach and @BeforeAll
Categories:
JUnit Annotations: @Before, @BeforeClass, @BeforeEach, and @BeforeAll Explained

Dive into the core JUnit annotations for test setup: @Before
, @BeforeClass
, @BeforeEach
, and @BeforeAll
. Understand their differences, execution order, and when to use each for effective test management in JUnit 4 and JUnit 5.
JUnit provides powerful annotations to manage the setup and teardown phases of your tests. Properly understanding and utilizing these annotations is crucial for writing clean, efficient, and maintainable test suites. This article will clarify the distinctions between @Before
, @BeforeClass
, @BeforeEach
, and @BeforeAll
, highlighting their roles in JUnit 4 and JUnit 5, and guiding you on when to apply each.
JUnit 4 Setup Annotations: @Before and @BeforeClass
In JUnit 4, test setup is primarily handled by two annotations: @Before
and @BeforeClass
. These annotations define methods that run before test methods, but they differ significantly in their scope and execution frequency.
@BeforeClass
must be static, as they run before any instance of the test class is created. Methods with @Before
are non-static and operate on a per-test-method basis.@Before
The @Before
annotation marks a method that should be executed before each test method in the class. This is ideal for setting up a fresh state for every individual test, ensuring that tests are isolated and don't interfere with each other. Common uses include initializing objects, resetting mock states, or preparing test data that needs to be unique for each test run.
@BeforeClass
The @BeforeClass
annotation designates a static method to be executed once before all test methods in the current test class. This is suitable for expensive setup operations that can be shared across all tests in the class, such as establishing a database connection, loading configuration files, or starting a server. Since it runs only once, it saves execution time compared to repeating the setup for every test.
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class JUnit4SetupTest {
private static String sharedResource;
private String testSpecificResource;
@BeforeClass
public static void setupClass() {
System.out.println("JUnit 4: @BeforeClass - Runs once before all tests");
sharedResource = "Database Connection";
// e.g., establish a database connection
}
@Before
public void setupTest() {
System.out.println("JUnit 4: @Before - Runs before each test");
testSpecificResource = "Fresh Test Data";
// e.g., initialize objects, reset mocks
}
@Test
public void testMethod1() {
System.out.println(" JUnit 4: Running testMethod1. Shared: " + sharedResource + ", Specific: " + testSpecificResource);
// Test logic using sharedResource and testSpecificResource
}
@Test
public void testMethod2() {
System.out.println(" JUnit 4: Running testMethod2. Shared: " + sharedResource + ", Specific: " + testSpecificResource);
// Test logic
}
}
Example of @Before and @BeforeClass in JUnit 4
JUnit 5 Setup Annotations: @BeforeEach and @BeforeAll
JUnit 5 (Jupiter) introduced a new set of annotations that are more semantically clear and offer enhanced capabilities. The JUnit 4 annotations have direct counterparts in JUnit 5, but with slightly different names and sometimes different requirements.
@BeforeEach
@BeforeEach
in JUnit 5 is the direct successor to JUnit 4's @Before
. It marks a method that will be executed before each test method (or @Test
, @RepeatedTest
, @ParameterizedTest
, @TestFactory
) in the current class. Like @Before
, it's used for setting up a consistent, isolated state for every individual test.
@BeforeAll
@BeforeAll
is the JUnit 5 equivalent of JUnit 4's @BeforeClass
. It marks a static method (or non-static if the test class is annotated with @TestInstance(Lifecycle.PER_CLASS)
) that will be executed once before all test methods in the current test class. It's used for expensive, shared setup operations, similar to @BeforeClass
.
@BeforeAll
methods can be non-static if the test class is annotated with @TestInstance(Lifecycle.PER_CLASS)
. This allows for instance-level setup that runs once for the entire class, which can be very convenient.import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
// Optional: Allows @BeforeAll to be non-static
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class JUnit5SetupTest {
private String sharedResource;
private String testSpecificResource;
@BeforeAll
void setupAll() {
System.out.println("JUnit 5: @BeforeAll - Runs once before all tests");
sharedResource = "Shared Configuration";
// e.g., start an embedded server
}
@BeforeEach
void setupEach() {
System.out.println("JUnit 5: @BeforeEach - Runs before each test");
testSpecificResource = "Individual Test Setup";
// e.g., create a new user for each test
}
@Test
void testMethodA() {
System.out.println(" JUnit 5: Running testMethodA. Shared: " + sharedResource + ", Specific: " + testSpecificResource);
// Test logic
}
@Test
void testMethodB() {
System.out.println(" JUnit 5: Running testMethodB. Shared: " + sharedResource + ", Specific: " + testSpecificResource);
// Test logic
}
}
Example of @BeforeEach and @BeforeAll in JUnit 5
Execution Order and Key Differences
Understanding the execution order is paramount to correctly using these annotations. The following diagram illustrates the typical flow for a test class with multiple test methods.
flowchart TD subgraph JUnit 4 BC4["@BeforeClass (static)"] --> B4["@Before"] B4 --> T4["@Test Method"] T4 --> A4["@After"] A4 --> AC4["@AfterClass (static)"] end subgraph JUnit 5 BA5["@BeforeAll (static/non-static)"] --> BE5["@BeforeEach"] BE5 --> T5["@Test Method"] T5 --> AE5["@AfterEach"] AE5 --> AA5["@AfterAll (static/non-static)"] end style BC4 fill:#f9f,stroke:#333,stroke-width:2px style B4 fill:#bbf,stroke:#333,stroke-width:2px style T4 fill:#cfc,stroke:#333,stroke-width:2px style A4 fill:#fbb,stroke:#333,stroke-width:2px style AC4 fill:#f9f,stroke:#333,stroke-width:2px style BA5 fill:#f9f,stroke:#333,stroke-width:2px style BE5 fill:#bbf,stroke:#333,stroke-width:2px style T5 fill:#cfc,stroke:#333,stroke-width:2px style AE5 fill:#fbb,stroke:#333,stroke-width:2px style AA5 fill:#f9f,stroke:#333,stroke-width:2px linkStyle 0 stroke-width:2px,fill:none,stroke:green; linkStyle 1 stroke-width:2px,fill:none,stroke:green; linkStyle 2 stroke-width:2px,fill:none,stroke:red; linkStyle 3 stroke-width:2px,fill:none,stroke:red; linkStyle 4 stroke-width:2px,fill:none,stroke:green; linkStyle 5 stroke-width:2px,fill:none,stroke:green; linkStyle 6 stroke-width:2px,fill:none,stroke:red; linkStyle 7 stroke-width:2px,fill:none,stroke:red;
Comparison of JUnit 4 and JUnit 5 Test Lifecycle Annotations
Here's a summary of the key differences and considerations:
JUnit 4 (
@Before
,@BeforeClass
):@BeforeClass
: Runs once per test class, must be static. Ideal for heavy, shared setup.@Before
: Runs before each test method, non-static. Ideal for per-test isolation.
JUnit 5 (
@BeforeEach
,@BeforeAll
):@BeforeAll
: Runs once per test class. Can be static by default, or non-static if the class is annotated with@TestInstance(Lifecycle.PER_CLASS)
. More flexible than@BeforeClass
.@BeforeEach
: Runs before each test method, non-static. Direct replacement for@Before
.
Choosing the right annotation depends on whether the setup needs to be shared across all tests in a class (once per class) or if each test requires its own fresh setup (once per test method).