Using JUnit 5 In Pre-Java 8 Projects
This post demonstrates how JUnit 5 can be used in pre-Java 8 projects and explains why it could be a good idea.
JUnit 5 requires at least Java 8 as runtime environment, so you want to update your whole project to Java 8. But sometimes there exists reason why you can’t immediately update your project to Java 8. For example, the version of your application server in production only supports Java 7. But an update isn’t be taken quickly because of some issues in your production code.
Now, the question is how can you use JUnit 5 without update your production code to Java 8?
In Maven (for sure also in Gradle) you can set up the Java version separately for production code and for test code.
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>7</source> <target>7</target> <testSource>8</testSource> <testTarget>8</testTarget> </configuration> </plugin> </plugins> </build>
Precondition is that you use a Java 8 JDK for your build.
If you try to use Java 8 feature in your Java 7 production code, Maven will fail the build.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project junit5-in-pre-java8-projects: Compilation failure [ERROR] /home/sparsick/dev/workspace/junit5-example/junit5-in-pre-java8-projects/src/main/java/Java7Class.java:[8,58] lambda expressions are not supported in -source 7 [ERROR] (use -source 8 or higher to enable lambda expressions)
Now you can introduce JUnit 5 in your project and start writing test with JUnit 5.
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> <!-- junit-vintage-engine is needed for running elder JUnit4 test with JUnit5--> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> </dependency>
Your old JUnit 4 tests need not be migrated, because JUnit 5 has a test engine, that can run JUnit 4 tests with JUnit 5. So use JUnit 5 for new tests and only migrate JUnit 4 tests if you have to touch them anyway.
Although you can’t update your production code to a newer Java version, it has some benefit to update your test code to a newer one.
The biggest benefit is that you can start learning new language feature during your daily work when you write tests. You don’t make the beginner’s mistake in the production code. You have access to new tools that can help improve your tests. For example, in JUnit 5 it’s more comfortable to write parameterized tests than in JUnit 4. In my experience, developer writes rather parameterized test with JUnit 5 than with JUnit 4 in a situation where parameterized test make sense.
The above described technique also works for other Java version. For example, your production code is on Java 11 and you want to use Java 12 feature in your test code. Another use case for this technique could be learning another JVM language like Groovy, Kotlin or Clojure in your daily work. Then use the new language in your test code.
One little pitfall has this approach. IntelliJ IDEA can’t set up the Java version for production and test, separately. Therefore, you have to set the whole project to Java 8. Only the Maven build gives you the feedback if your production code uses the right Java version.
Links
Published on Java Code Geeks with permission by Sandra Parsick, partner at our JCG program. See the original article here: Using JUnit 5 In Pre-Java 8 Projects Opinions expressed by Java Code Geeks contributors are their own. |