JUnit 5 tool support has come a long way since its early days in 2017, so setting JUnit 5 up in your favorite IDE or build tool should be fairly straight-forward. Here's how to do it in IntelliJ, Eclipse, Maven, Gradle, or, if everything else fails, on the command line.
▚Writing Tests
To write tests, you need the Jupiter API artifact:
- Group ID: org.junit.jupiter
- Artifact ID: junit-jupiter-api
- Version: 5.2.0
- Scope: test
Including it in your project with your favorite build tool is all it takes to write tests. So lets do that and quickly create our first test:
import org.junit.jupiter.api.Test;
class HelloWorldTest {
@Test
void helloJUnit5() {
System.out.println("Hello, JUnit 5.");
}
}
See ma, no public
!
Cool, right?
I won't go into it here, though - check out the post on basics for more details.
▚Running Tests
A new aspect of JUnit 5, and I'll go into more details when we discuss its architecture, are engines. An engine is in charge of executing all tests with a specific API. For the Jupiter API, which we just added and used, that would be the Jupiter engine:
- Group ID: org.junit.jupiter
- Artifact ID: junit-jupiter-engine
- Version: 5.2.0
- Scope: test or testRuntime
Because the test API evolves over time, the engine must do the same and so it's best for the project to specify the exact engine version in its build configuration.
▚Build Tool Support
Initially, the JUnit 5 team implemented a rudimentary Gradle plugin and Maven Surefire provider as proofs of concept.
In the meantime, both tools have implemented native support, so there's no need to use junit-platform-gradle-plugin
or junit-platform-surefire-provider
anymore - you can remove them.
▚Gradle
Native JUnit 5 support is available since Gradle 4.6.
All you need to do is activate it in the test
task:
test {
useJUnitPlatform()
}
As I explained, you need the engine at test run time, so the tests can actually be executed:
testRuntime "org.junit.jupiter:junit-jupiter-engine:5.2.0"
For more details on the Gradle integration, check its documentation.
▚Maven
Maven's surefire provider has native support for JUnit 5 since version 2.22.0. It picks up the test engine from your regular dependencies:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
▚IDE Support
Eclipse and IntelliJ natively support JUnit 5, but for NetBeans I couldn't even find an issue.
▚IntelliJ IDEA
IntelliJ IDEA supports JUnit 5 since 2016.2, but I strongly recommend to use at least 2017.3. Until then, IntelliJ used to come with its own version of the Jupiter engine, which leads to problems if your project does not depend on the matching API version. Since 2017.3, IntelliJ selects the engine based on the API version you depend on.
▚Eclipse
Eclipse supports JUnit 5 since Oxygen.1a (4.7.1a), but I didn't figure out how it picks up the engine.
▚JUnit 4 Runner
If the support for your tool of choice does not suffice, you can try the detour via JUnit 4: A test runner called JUnitPlatform
can be used to run new tests as part of a JUnit 4 run.
You find it in its own artifact, which you have to add to your project (on top of JUnit 4 and the JUnit 5 Jupiter API and engine):
- Group ID: org.junit.platform
- Artifact ID: junit-platform-runner
- Version: 1.2.0
- Scope: test or testRuntime
To run all tests in a project, it is easiest to create a test suite for them:
package org.codefx.demo.junit5;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.runner.SelectPackages;
import org.junit.runner.RunWith;
@RunWith(JUnitPlatform.class)
@SelectPackages({ "org.codefx.demo.junit5" })
public class TestWithJUnit5 { }
Note that the class has to be a regular JUnit 4 test class, i.e.
it has to adhere to the common naming convention and must be public.
The @SelectPackages
-annotation interprets packages as a hierarchy so it runs all tests in all packages prefixed with org.codefx.demo.junit5
.
If you prefer, you can use the same runner directly on the JUnit 5 test classes; in that case they have to be public.
Now we're done!
Even if slightly outdated, your favorite IDE and build tool will happily run the classes annotated with @RunWith(JUnitPlatform.class)
and hence the new JUnit 5 tests.
Due to the detour through JUnit 4, some features may not be supported, e.g. IDEs won't run individual test methods. But if the other approaches do not work for you, this can be an acceptable and tool independent solution.
▚Command Line For The Win!
In case all of this is too fancy for you, try the console launcher, which lets you run the tests directly from the command line. The best way to use it is to download the standalone JAR, which comes with all the required dependencies.
Ignoring your dependencies (e.g. from production code or on test libraries) you can then use it as follows:
# run all tests
$ java -jar junit-platform-console-standalone.jar
--class-path ${path_to_compiled_test_classes}
--scan-class-path
# run a specific test
$ java -jar junit-platform-console-standalone
--class-path ${path_to_compiled_test_classes}
--select-class ${fully_qualified_test_class_name}
To include dependencies, add them to the class path after --class-path
.
If you're doing this in a Maven project, your command might look like this:
java -jar junit-platform-console-standalone
--class-path target/test-classes:target/classes
--scan-class-path
▚Compatibility
As you might have noticed, JUnit 5 occupies new namespaces: org.junit.jupiter
, org.junit.platform
, and org.junit.vintage
(which we didn't see yet).
I explain their meaning in a post dedicated to JUnit's architecture - for now this only means that there will be no conflicts when different JUnit versions are used in the same project.
Indeed, a project can contain and run tests from different versions without problems, which allows a slow migration to JUnit 5. We will revisit this topic when we're exploring migration paths (stay tuned).
A project can contain and run tests from different JUnit versions
Assertion libraries like Hamcrest and AssertJ, which communicate with JUnit via exceptions, continues to work in the new version.
Check out the complete version of HelloWorldTest
for an example using Mockito and AssertJ.
▚Reflection
For our JUnit 5 setup we've included junit-jupiter-api
and the matching junit-jupiter-engine
, in our project, written a first minimal test case, and made sure it runs in various IDEs and build tools.
The next post explores the basics of how to write tests in JUnit 5.