JUnit is one of the most popular testing frameworks for the Java programming language. It has also been important in the development of Test Driven Development, or TDD. In 2018, the latest version of this framework was released, JUnit5, and many programmers who use the JUnit platform have had to decide whether or not to refactor their existing code that is written in a previous version of JUnit. <tl;dr> This article is about mixing JUnit4 and JUnit5 into your ongoing project to get JUnit5 benefits without refactoring all already written JUnit4 tests. The intention is not to describe JUnit5 in depth but give a guideline to migrate JUnit5 support. JUnit5 has many benefits that developers will want to use. Better exception handling, better parameterized tests, multiple and so on. If you are like me, and want to migrate into a newer platform as soon as possible, you probably also know what a pain it is to do so. testrunners Fortunately, JUnit5 has very good support to work side by side with version 4. I think this is important in projects where there are hundreds of already written tests. To refactor all of them is enormous work and it is much easier to give up than go on with adopting something new. In the following post, I’ve broken down the steps you will need to follow in order to introduce JUtin5 support for tests, while still supporting JUnit4 tests. Lets assume we have project gradle plugins {id 'java'id 'com.adarshr.test-logger' version '1.6.0'} group 'rainoko'version '1.0-SNAPSHOT' sourceCompatibility = 11 repositories {mavenCentral()} dependencies {testCompile('junit:junit:4.12')} wrapper {gradleVersion = '5.2.1'} with some simple class SimpleNaturalCalculator.java package ee.rainoko.junit5demo; public class SimpleNaturalCalculator {public int addition(int arg1, int arg2) {return arg1 + arg2;} public int substraction(int arg1, int arg2) {return arg1 - arg2;} public int multiplication(int arg1, int arg2) {return arg1 * arg2;} public int division(int arg1, int arg2) {return arg1 / arg2;}} And covered with test SimpleNaturalCalculatorTest.java package ee.rainoko.junit5demo; import org.junit.*; import static org.junit.Assert.*; public class SimpleNaturalCalculatorJunit4Test {@Testpublic void shouldAdd() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.addition(1, 2); _assertEquals_(3, result); } @Testpublic void shouldSubstract() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2); _assertEquals_(-1, result); } @Testpublic void shouldMultiply() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2); _assertEquals_(2, result); } @Testpublic void shouldDivide() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.division(1, 2); _assertEquals_(0, result); }} As we see this is a JUnit4 test using annotations from org.junit Lets run this with the following command: gradlew test And we get this result: ee.rainoko.junit5demo.SimpleNaturalCalculatorTest Test shouldAdd PASSEDTest shouldDivide PASSEDTest shouldSubstract PASSEDTest shouldMultiply PASSED Now we have been setting up a standard project with JUnit4. Lets proceed. Our goal is to introduce JUnit5 support. Unlike version 4 the 5 has modularized library structure: [https://junit.org/junit5/docs/current/user-guide/] JUnit 5 = + + JUnit Platform JUnit Jupiter JUnit Vintage The serves as a foundation for on the JVM. [https://junit.org/junit5/docs/current/user-guide/] JUnit Platform launching testing frameworks is the combination of the new and for writing tests and extensions in JUnit 5. [https://junit.org/junit5/docs/current/user-guide/] JUnit Jupiter programming model extension model provides a for running JUnit 3 and JUnit 4 based tests on the platform.[https://junit.org/junit5/docs/current/user-guide/] JUnit Vintage TestEngine Now knowing that, lets add JUnit5 support. For starters, to prevent confusion, lets rename our junit4 test class to SimpleNaturalCalculatorJunit4Test.java Lets add JUnit5 dependencies to gradle // JUnit JupitertestImplementation('org.junit.jupiter:junit-jupiter:5.4.0') // JUnit VintagetestCompileOnly('junit:junit:4.12')testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.4.0') {because 'allows JUnit 3 and JUnit 4 tests to run'} As you see we added junit-jupiter. Also marked junit:4.12 as testCompileOnly. This library is still needed for compilation if we want to have our old junit4 tests without any modification. And then we also added junit-vintage-engine to give junit platform ability to run JUnit4 tests side by side with JUnit5 tests. Finally we need to add also command to use JUnit5 platform for running tests in gradle test {useJUnitPlatform()} No lets add JUnit5 test class SimpleNaturalCalculatorJunit5Test.java package ee.rainoko.junit5demo; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions. ; assertEquals class SimpleNaturalCalculatorJunit5Test {@Testvoid shouldAdd() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.addition(1, 2); _assertEquals_(3, result); } @Testvoid shouldSubstract() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2); _assertEquals_(-1, result); } @Testvoid shouldMultiply() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2); _assertEquals_(2, result); } @Testvoid shouldDivide() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.division(1, 2); _assertEquals_(0, result); }} As you can confirm from imports we now use junit jupiter. Notice that test class is package-protected and methods also. JUnit5 now allows us to use package-protected modifiers, which, as I think, better exposes the purpose of access modifiers of java. Lets run our tests gradlew test And we have output ee.rainoko.junit5demo.SimpleNaturalCalculatorJunit4Test Test shouldAdd PASSEDTest shouldDivide PASSEDTest shouldSubstract PASSEDTest shouldMultiply PASSED ee.rainoko.junit5demo.SimpleNaturalCalculatorJunit5Test Test shouldAdd() PASSEDTest shouldDivide() PASSEDTest shouldSubstract() PASSEDTest shouldMultiply() PASSED We can even use mixed test class. package ee.rainoko.junit5demo; import static org.junit.jupiter.api.Assertions. ; assertEquals public class SimpleNaturalCalculatorJunitMixedTest {@org.junit.Testpublic void shouldAddJunit4() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.addition(1, 2); org.junit.Assert._assertEquals_(3, result); org.junit.jupiter.api.Assertions._assertEquals_(3, result); } @org.junit.jupiter.api.Testvoid shouldAddJunit5() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.addition(1, 2); org.junit.Assert._assertEquals_(3, result); org.junit.jupiter.api.Assertions._assertEquals_(3, result); } @org.junit.Testpublic void shouldSubstractJunit4() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2); _assertEquals_(-1, result); } @org.junit.jupiter.api.Testvoid shouldSubstractJunit5() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2); _assertEquals_(-1, result); } @org.junit.Testpublic void shouldMultiplyJunit4() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2); _assertEquals_(2, result); } @org.junit.jupiter.api.Testvoid shouldMultiplyJunit5() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2); _assertEquals_(2, result); } @org.junit.Testpublic void shouldDivideJunit4() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.division(1, 2); _assertEquals_(0, result); } @org.junit.jupiter.api.Testvoid shouldDivideJunit5() {SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.division(1, 2); _assertEquals_(0, result); }} As you can see now we have annotations from org.junit and from org.junit.jupiter.api. The JUnit5 platform chooses right engine for each test method. You can even mix asserts from old JUnit4 package and new JUnit5 package in either of test type. gradlew test And we get output ee.rainoko.junit5demo.SimpleNaturalCalculatorJunit4Test Test shouldAdd PASSEDTest shouldDivide PASSEDTest shouldSubstract PASSEDTest shouldMultiply PASSED ee.rainoko.junit5demo.SimpleNaturalCalculatorJunitMixedTest Test shouldAddJunit4 PASSEDTest shouldDivideJunit4 PASSEDTest shouldMultiplyJunit4 PASSEDTest shouldSubstractJunit4 PASSED ee.rainoko.junit5demo.SimpleNaturalCalculatorJunit5Test Test shouldAdd() PASSEDTest shouldDivide() PASSEDTest shouldSubstract() PASSEDTest shouldMultiply() PASSED ee.rainoko.junit5demo.SimpleNaturalCalculatorJunitMixedTest Test shouldAddJunit5() PASSEDTest shouldDivideJunit5() PASSEDTest shouldMultiplyJunit5() PASSEDTest shouldSubstractJunit5() PASSED SUCCESS: Executed 16 tests in 1s JUnit4 and JUnit5 have different @Before… annotations. If you need to mix them add both annotations to your setUp and tearDown methods. Be aware Hope this article helpt to migrate to JUnit5 even if your project using heavily JUnit4 tests and . get benefits now not tomorrow Read more There are plenty of good examples and articles about JUnit5. Read them also https://junit.org/junit5/docs/current/user-guide/ https://www.baeldung.com/junit-5 https://github.com/junit-team/junit5-samples