JUnit 4 to 5 Migration: Tests with Multiple @Before Methods Fail Due to Arbitrary Execution Order

Open
#1,207 1 comment 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@ApekshaAmbala is already working on this.

Since Oct 23, 2026.

  • #1246 by @ApekshaAmbala — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
java
Domain
testing

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

junit recipe

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

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openrewrite/rewrite-testing-frameworks

All issues in openrewrite/rewrite-testing-frameworks

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.