JUnit 4 to 5 Migration: Tests with Multiple @Before Methods Fail Due to Arbitrary Execution Order
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 55/100
Research direction
Start by reading the JUnit4to5Migration recipe and its tests for converting JUnit 4 @Before methods to JUnit 5 @BeforeEach. Reproduce the reported failure with multiple setup methods that depend on execution order, then check whether the migration can detect or preserve that dependency without silently changing behavior. Done when the recipe handles this case safely and a regression test covers it.
Written by the indexing model from the issue text.
Description
What version of OpenRewrite are you using?
I am using
- OpenRewrite - Moderne CLI v4.11.1 (
modw) - Recipe:
org.openrewrite.java.testing.junit5.JUnit4to5Migration - Maven plugin v3.9.16
How are you running OpenRewrite?
I am using the Moderne CLI with the following command:
modw run . --recipe=org.openrewrite.java.testing.junit5.JUnit4to5Migration
My project is a single module Maven project.
What is the smallest, simplest way to reproduce the problem?
Before migration (JUnit 4):
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
public class MultipleBeforeMethodsTest {
private List<String> executionOrder;
@Before
public void first() {
if (executionOrder == null) {
executionOrder = new ArrayList<>();
}
executionOrder.add("first");
System.out.println("First");
}
@Before
public void second() {
executionOrder.add("second");
System.out.println("Second");
}
@Before
public void third() {
executionOrder.add("third");
System.out.println("Third");
}
@Test
public void testExecutionOrder() {
// Some Tests
}
}
✅ JUnit 4 Result: All tests pass because methods execute in alphabetical order: first → second → third
What did you expect to see?
After running the migration recipe, I expected either:
- The recipe to detect this pattern and warn that multiple @Before methods with order dependencies will break,
OR - The recipe to automatically consolidate the multiple @BeforeEach methods into a single method to preserve order,
OR - The recipe to add @Order annotations to preserve the execution order explicitly
At minimum, the migration should not silently break working tests.
What did you see instead?
The recipe automatically converted the code to:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.List;
public class MultipleBeforeMethodsTest {
private List<String> executionOrder;
@BeforeEach // ⚠️ No guaranteed order!
public void first() {
if (executionOrder == null) {
executionOrder = new ArrayList<>();
}
executionOrder.add("first");
System.out.println("First");
}
@BeforeEach // ⚠️ Might run before first()!
public void second() {
executionOrder.add("second"); // 💥 NullPointerException if first() hasn't run
System.out.println("Second");
}
@BeforeEach // ⚠️ Arbitrary order
public void third() {
executionOrder.add("third"); // 💥 NullPointerException if first() hasn't run
System.out.println("Third");
}
@Test
public void testExecutionOrder() {
// Some Tests
}
}
❌ JUnit 5 Result: Tests fail because JUnit 5 executes @BeforeEach methods in arbitrary order, not alphabetical order.
What is the full stack trace of any errors you encountered?
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.sto.test.app.MultipleBeforeMethodsTest
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.089 s <<< FAILURE!
[ERROR] com.sto.test.app.MultipleBeforeMethodsTest.testExecutionOrder -- Time elapsed: 0.043 s <<< ERROR!
java.lang.NullPointerException: Cannot invoke "java.util.List.add(Object)" because "this.executionOrder" is null
at com.sto.test.app.MultipleBeforeMethodsTest.second(MultipleBeforeMethodsTest.java:25)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
Root Cause:
JUnit 4: Multiple @Before methods execute in alphabetical/declaration order (predictable)
JUnit 5: Multiple @BeforeEach methods execute in arbitrary order (unpredictable)
Are you interested in contributing a fix to OpenRewrite?
I'm open to contributing
- Dominant language
- Java
- Stars
- 100
- Forks
- 109
- Avg merge
- 3h 43m
- Merged PRs (30d)
- 82
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openrewrite/rewrite-testing-frameworks
-
Recipe quality triage: remaining fixes, wiring and polish (A1–O8)May be free again @tashen247 claimed this 17 days ago, and no pull request is open. Opengood first issue
Difficulty 4/5 3-5 days Newbie friendliness 48/100
openrewrite/rewrite-testing-frameworks#1211 · 2 comments ·
Maintainers usually reply within 1 day
-
JUnit4to5Migration - undiscovered or invalid Kotlin testsPossibly taken @hugoncosta claimed this 28 days ago. Openbug
Difficulty 4/5 3-5 days Newbie friendliness 42/100
openrewrite/rewrite-testing-frameworks#1188 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
openrewrite/rewrite-testing-frameworks#1167 ·
Maintainers usually reply within 1 day
-
`ParameterizedRunnerToParameterized` silently skips classes whose `@Parameters` method is inherited, leaving a partially migrated class thatPossibly taken @mohitduhan19 claimed this 43 days ago. Openbug
Difficulty 4/5 3-5 days Newbie friendliness 68/100
openrewrite/rewrite-testing-frameworks#1126 ·
Maintainers usually reply within 1 day
-
`JUnit4to5Migration` moves `Parameterized` parameter assignment after `@BeforeEach`, so setup methods read nullPossibly taken @mohitduhan19 claimed this 37 days ago. Openbug
Difficulty 4/5 3-5 days Newbie friendliness 70/100
openrewrite/rewrite-testing-frameworks#1125 ·
Maintainers usually reply within 1 day
All issues in openrewrite/rewrite-testing-frameworks
Similar issues
-
Four TestConstraintBasedAlgorithm tests pass when nothing is thrownPossibly taken @sharanggupta claimed this today. Open
Difficulty 1/5 1-3 hours Newbie friendliness 85/100
-
bug documentation good first issue help wanted priority low size XS
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
martin-francois/symphony-trello#1351 ·
Maintainers usually reply within 1 day
-
Add test coverage for ConvertUtil.parseDate() with NULL inputPossibly taken @mirajul-mollah7 claimed this today. Open
Difficulty 1/5 Under an hour Newbie friendliness 78/100
eclipse-sw360/sw360#4792 · 1 comment ·
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
aws/aws-emulator#30 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 4 days