As mentioned in JUnit5 documentation, it is possible to integrate JUnit4 with JUnit5:
JUnit provides a gentle migration path via a JUnit Vintage test engine which allows existing tests based on JUnit 3 and JUnit 4 to be executed
using the JUnit Platform infrastructure. Since all classes and annotations specific to JUnit Jupiter reside under a new org.junit.jupiter base
package, having both JUnit 4 and JUnit Jupiter in the classpath does not lead to any conflicts.
However, maintaining both systems is a temporary solution. This rule flags all the annotations from JUnit4 which would need to be migrated to
JUnit5, hence helping migration of a project.
Here is the list of JUnit4 annotations tracked by the rule, with their corresponding annotations in JUnit5:
JUnit4 |
JUnit5 |
org.junit.Test
|
org.junit.jupiter.api.Test
|
org.junit.Before
|
org.junit.jupiter.api.BeforeEach
|
org.junit.After
|
org.junit.jupiter.api.AfterEach
|
org.junit.BeforeClass
|
org.junit.jupiter.api.BeforeAll
|
org.junit.AfterClass
|
org.junit.jupiter.api.AfterAll
|
org.junit.Ignore
|
org.junit.jupiter.api.Disabled
|
Note that the following annotations might requires some rework of the tests to have JUnit5 equivalent behavior. A simple replacement of the
annotation won’t work immediately:
JUnit4 |
JUnit5 |
org.junit.experimental.categories.Category
|
org.junit.jupiter.api.Tag
|
org.junit.Rule
|
org.junit.jupiter.api.extension.ExtendWith
|
org.junit.ClassRule
|
org.junit.jupiter.api.extension.RegisterExtension
|
org.junit.runner.RunWith
|
org.junit.jupiter.api.extension.ExtendWith
|
Noncompliant code example
package org.foo;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
@RunWith(MyJUnit4Runner.class)
public class MyJUnit4Test {
@BeforeClass
public static void beforeAll() {
System.out.println("beforeAll");
}
@AfterClass
public static void afterAll() {
System.out.println("AfterAll");
}
@Before
public void beforeEach() {
System.out.println("beforeEach");
}
@After
public void afterEach() {
System.out.println("afterEach");
}
@Test
public void test1() throws Exception {
System.out.println("test1");
}
public interface SomeTests { /* category marker */ }
@Test
@Category(SomeTests.class)
public void test2() throws Exception {
System.out.println("test2");
}
@Test
@Ignore("Requires fix of #42")
public void ignored() throws Exception {
System.out.println("ignored");
}
}
Compliant solution
package org.foo;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MyJUnit5Extension.class)
class MyJUnit5Test {
@BeforeAll
static void beforeAll() {
System.out.println("beforeAll");
}
@AfterAll
static void afterAll() {
System.out.println("afterAll");
}
@BeforeEach
void beforeEach() {
System.out.println("beforeEach");
}
@AfterEach
void afterEach() {
System.out.println("afterEach");
}
@Test
void test1() {
System.out.println("test1");
}
@Test
@Tag("SomeTests")
void test2() {
System.out.println("test2");
}
@Test
@Disabled("Requires fix of #42")
void disabled() {
System.out.println("ignored");
}
}