Each execution of a @RepeatedTest is treated as a full test invocation in JUnit 5. This means lifecycle callbacks are applied consistently for every repetition.
Why Lifecycle Awareness Is Critical
State leakage between repetitions can lead to misleading test results. JUnit 5 ensures that @BeforeEach and @AfterEach run before and after every repetition, while @BeforeAll and @AfterAll still execute only once per class.
Example
package com.logicbig.example;
import org.junit.jupiter.api.*;
public class RepeatedTestLifecycleTest {
@BeforeAll
static void beforeAll() {
System.out.println("before all");
}
@BeforeEach
void beforeEach() {
System.out.println("before each");
}
@RepeatedTest(2)
void retryOperation() {
System.out.println("run");
}
@AfterEach
void afterEach() {
System.out.println("after each");
}
@AfterAll
static void afterAll() {
System.out.println("after all");
}
}
Output$ mvn test -Dtest=RepeatedTestLifecycleTest [INFO] Scanning for projects... [INFO] [INFO] --< com.logicbig.example:junit-5-repeated-test-lifecycle-interaction >-- [INFO] Building junit-5-repeated-test-lifecycle-interaction 1.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ junit-5-repeated-test-lifecycle-interaction --- [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-repeated-tests\junit-5-repeated-test-lifecycle-interaction\src\main\resources [INFO] [INFO] --- compiler:3.11.0:compile (default-compile) @ junit-5-repeated-test-lifecycle-interaction --- [INFO] No sources to compile [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ junit-5-repeated-test-lifecycle-interaction --- [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-repeated-tests\junit-5-repeated-test-lifecycle-interaction\src\test\resources [INFO] [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ junit-5-repeated-test-lifecycle-interaction --- [INFO] Changes detected - recompiling the module! :input tree [WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent! [INFO] Compiling 1 source file with javac [debug target 17] to target\test-classes [INFO] [INFO] --- surefire:3.5.0:test (default-test) @ junit-5-repeated-test-lifecycle-interaction --- [INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- before all before each run after each before each run after each after all [INFO] +--com.logicbig.example.RepeatedTestLifecycleTest - 0.108 ss [INFO] | +-- [OK] retryOperation() repetition 1 of 2 - 0.035 ss [INFO] | '-- [OK] retryOperation() repetition 2 of 2 - 0.003 ss [INFO] [INFO] Results: [INFO] [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.876 s [INFO] Finished at: 2025-12-27T08:46:48+08:00 [INFO] ------------------------------------------------------------------------
Output Analysis
The output demonstrates that @BeforeEach and @AfterEach methods are executed for every repetition, confirming that each run is isolated from the others. This behavior is essential when validating retry logic, flaky integrations, or scenarios where a single failure must not influence subsequent repetitions.
Example ProjectDependencies and Technologies Used: - junit-jupiter-engine 6.0.1 (Module "junit-jupiter-engine" of JUnit)
Version Compatibility: 5.0.0 - 6.0.1 Version compatibilities of junit-jupiter-engine with this example:
- 5.0.0
- 5.0.1
- 5.0.2
- 5.0.3
- 5.1.0
- 5.1.1
- 5.2.0
- 5.3.0
- 5.3.1
- 5.3.2
- 5.4.0
- 5.4.1
- 5.4.2
- 5.5.0
- 5.5.1
- 5.5.2
- 5.6.0
- 5.6.1
- 5.6.2
- 5.6.3
- 5.7.0
- 5.7.1
- 5.7.2
- 5.8.0
- 5.8.1
- 5.8.2
- 5.9.0
- 5.9.1
- 5.9.2
- 5.9.3
- 5.10.0
- 5.10.1
- 5.10.2
- 5.10.3
- 5.10.4
- 5.10.5
- 5.11.0
- 5.11.1
- 5.11.2
- 5.11.3
- 5.11.4
- 5.12.0
- 5.12.1
- 5.12.2
- 5.13.0
- 5.13.1
- 5.13.2
- 5.13.3
- 5.13.4
- 5.14.0
- 5.14.1
- 6.0.0
- 6.0.1
Versions in green have been tested.
- JDK 25
- Maven 3.9.11
|