Migrating from JUnit 4 to JUnit 5
JUnit 5 introduces modular architecture, better extension support, and improved parameterized tests, but many projects still rely on JUnit…
Migrating from JUnit 4 to JUnit 5
Photo by Liana Mikah on Unsplash
JUnit 5 introduces modular architecture, better extension support, and improved parameterized tests, but many projects still rely on JUnit 4 tests. The Vintage Engine allows running JUnit 4 tests inside JUnit 5, making it possible to migrate gradually.
1. Key Differences Between JUnit 4 and JUnit 5

2. Hybrid Approach Using JUnit Vintage Engine
Step 1: Update Dependencies in pom.xml
Add the JUnit 5 dependencies along with the Vintage Engine to continue running JUnit 4 tests.
<dependencies>
<!-- JUnit 5 API -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
<!-- JUnit 5 Engine (Runs JUnit 5 Tests) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
<!-- JUnit Vintage Engine (Runs JUnit 4 Tests in JUnit 5) -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
<!-- JUnit 4 (Only Needed for Legacy Tests) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
✅ Why This Works?
- JUnit Jupiter Engine runs JUnit 5 tests.
- JUnit Vintage Engine allows JUnit 4 tests to run inside JUnit 5.
- The JUnit 4 dependency ensures compatibility.
Step 2: Running JUnit 4 and JUnit 5 Tests Together
✅ JUnit 4 Test (Still Works with Vintage Engine)
import org.junit.*;
public class JUnit4Test {
@BeforeClass
public static void init() {
System.out.println("JUnit 4: Before Class");
}
@Before
public void setup() {
System.out.println("JUnit 4: Before Test");
}
@Test
public void testAddition() {
Assert.assertEquals(5, 2 + 3);
}
@After
public void teardown() {
System.out.println("JUnit 4: After Test");
}
@AfterClass
public static void cleanup() {
System.out.println("JUnit 4: After Class");
}
}
✅ JUnit 5 Test
import org.junit.jupiter.api.*;
class JUnit5Test {
@BeforeAll
static void setup() {
System.out.println("JUnit 5: Before All");
}
@BeforeEach
void init() {
System.out.println("JUnit 5: Before Each");
}
@Test
void testMultiplication() {
Assertions.assertEquals(6, 2 * 3);
}
@AfterEach
void teardown() {
System.out.println("JUnit 5: After Each");
}
@AfterAll
static void cleanup() {
System.out.println("JUnit 5: After All");
}
}
✅ JUnit 4 and JUnit 5 tests will run together in the same test suite.
Step 3: Gradual Migration
- Keep JUnit 4 Tests Running with Vintage Engine ✅
- Convert JUnit 4 Tests to JUnit 5 Incrementally 🔄
- Remove
junit-vintage-engineOnce All Tests are Migrated 🛑
3. How to Migrate JUnit 4 Tests to JUnit 5
A. Convert Test Annotations

Example Conversion:
JUnit 4
import org.junit.*;
public class OldTest {
@Before
public void setup() {
System.out.println("Setting up");
}
@Test(expected = ArithmeticException.class)
public void testException() {
int result = 1 / 0; // Should throw ArithmeticException
}
@Ignore
@Test
public void ignoredTest() {
System.out.println("This test is ignored");
}
}
JUnit 5 (Converted)
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
class NewTest {
@BeforeEach
void setup() {
System.out.println("Setting up");
}
@Test
void testException() {
assertThrows(ArithmeticException.class, () -> {
int result = 1 / 0;
});
}
@Disabled
@Test
void ignoredTest() {
System.out.println("This test is ignored");
}
}
B. Convert Assertions
JUnit 4 JUnit 5

Example:
JUnit 4 Assertion
Assert.assertEquals(5, 2 + 3);
JUnit 5 Assertion
Assertions.assertEquals(5, 2 + 3);
C. Convert Parameterized Tests
JUnit 4:
import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
@RunWith(Parameterized.class)
public class ParamTest {
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{1, 2, 3},
{2, 3, 5},
{3, 5, 8}
});
}
private int a, b, expected;
public ParamTest(int a, int b, int expected) {
this.a = a;
this.b = b;
this.expected = expected;
}
@Test
public void testAddition() {
Assert.assertEquals(expected, a + b);
}
}
JUnit 5:
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.*;
class ParamTest {
@ParameterizedTest
@CsvSource({
"1,2,3",
"2,3,5",
"3,5,8"
})
void testAddition(int a, int b, int expected) {
assertEquals(expected, a + b);
}
}
✅ No need for @RunWith(Parameterized.class) in JUnit 5!
Final Steps
- ✅ Enable JUnit 5 with Vintage Engine (for hybrid execution).
- 🔄 Gradually migrate tests to JUnit 5 syntax.
- 🛑 Remove JUnit 4 dependencies & Vintage Engine once migration is complete.
Would you like a step-by-step automated migration script for JUnit 5? 🚀
Click here for automated Script for migration.
메타데이터
- post_id
- 860613c564d3
- slug
- migrating-from-junit-4-to-junit-5-860613c564d3
- url
- https://medium.com/@rakeshsinghania02/migrating-from-junit-4-to-junit-5-860613c564d3
- canonical_url
- https://medium.com/@rakeshsinghania02/migrating-from-junit-4-to-junit-5-860613c564d3
- author_url
- https://medium.com/@rakeshsinghania02
- status
- ok
- fetched_at
- 2026-07-20 15:35:23