Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
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 testrunners 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.
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 gradle project
plugins { id 'java' id 'com.adarshr.test-logger' version '1.6.0'}group 'rainoko'version '1.0-SNAPSHOT'sourceCompatibility = 11repositories { 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 { @Test public void shouldAdd() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.addition(1, 2);assertEquals(3, result); } @Test public void shouldSubstract() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2);assertEquals(-1, result); } @Test public void shouldMultiply() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2);assertEquals(2, result); } @Test public 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 PASSED Test shouldDivide PASSED Test shouldSubstract PASSED Test 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 JUnit Platform serves as a foundation for launching testing frameworks on the JVM. [https://junit.org/junit5/docs/current/user-guide/]
JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. [https://junit.org/junit5/docs/current/user-guide/]
JUnit Vintage provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform.[https://junit.org/junit5/docs/current/user-guide/]
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 { @Test void shouldAdd() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.addition(1, 2);assertEquals(3, result); } @Test void shouldSubstract() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2);assertEquals(-1, result); } @Test void shouldMultiply() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2);assertEquals(2, result); } @Test void 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 PASSED Test shouldDivide PASSED Test shouldSubstract PASSED Test shouldMultiply PASSED
ee.rainoko.junit5demo.SimpleNaturalCalculatorJunit5Test
Test shouldAdd() PASSED Test shouldDivide() PASSED Test shouldSubstract() PASSED Test 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.Test public 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.Test void 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.Test public void shouldSubstractJunit4() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2);assertEquals(-1, result); } @org.junit.jupiter.api.Test void shouldSubstractJunit5() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.substraction(1, 2);assertEquals(-1, result); } @org.junit.Test public void shouldMultiplyJunit4() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2);assertEquals(2, result); } @org.junit.jupiter.api.Test void shouldMultiplyJunit5() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.multiplication(1, 2);assertEquals(2, result); } @org.junit.Test public void shouldDivideJunit4() { SimpleNaturalCalculator calculator = new SimpleNaturalCalculator(); int result = calculator.division(1, 2);assertEquals(0, result); } @org.junit.jupiter.api.Test void 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 PASSED Test shouldDivide PASSED Test shouldSubstract PASSED Test shouldMultiply PASSED
ee.rainoko.junit5demo.SimpleNaturalCalculatorJunitMixedTest
Test shouldAddJunit4 PASSED Test shouldDivideJunit4 PASSED Test shouldMultiplyJunit4 PASSED Test shouldSubstractJunit4 PASSED
ee.rainoko.junit5demo.SimpleNaturalCalculatorJunit5Test
Test shouldAdd() PASSED Test shouldDivide() PASSED Test shouldSubstract() PASSED Test shouldMultiply() PASSED
ee.rainoko.junit5demo.SimpleNaturalCalculatorJunitMixedTest
Test shouldAddJunit5() PASSED Test shouldDivideJunit5() PASSED Test shouldMultiplyJunit5() PASSED Test shouldSubstractJunit5() PASSED
SUCCESS: Executed 16 tests in 1s
Be aware JUnit4 and JUnit5 have different @Before⊠annotations. If you need to mix them add both annotations to your setUp and tearDown methods.
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
Mixing JUnit4 and JUnit5 was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.