Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JUnit 5 with Java 9 without Maven or Gradle

The Description:

I would like to create a JUnit test using JUnit 5 in Eclipse (Oxygen 4.7.1a). This JUnit test should be inside a seperate src folder called Test. However, I ran into the following problems as I'm new to JUnit and Java 9.

I do not want to use build tools like Gradle or Maven for this.

The Problem:

As I've got two different src folders, one for the projects src and one for the test cases:

  • Do I need two module-info.java files? (one for each src folder)
  • Which modules are required in my module-info.java file for JUnit 5 to work?
like image 1000
ShadowDragon Avatar asked Oct 11 '17 19:10

ShadowDragon


People also ask

What dependency do I need for JUnit 5?

Please note that JUnit 5 requires minimum Java 8 at runtime.

Is JUnit Jupiter the same as JUnit 5?

It's important, however, to understand that the two terms are not the same. JUnit Jupiter is the API for writing tests using JUnit version 5. JUnit 5 is the project name (and version) that includes the separation of concerns reflected in all three major modules: JUnit Jupiter, JUnit Platform, and JUnit Vintage.

How do I run a JUnit 5 test suite?

Creating Test Suites Creating suites is easy. Just add the @Suite annotation of a class and start including or excluding the test classes and methods into the suite. When we want to run the suite, simply run it as a normal JUnit test class and it will execute all the included tests in the suite.

Is JUnit 5 backwards compatible?

Please note that JUnit 5 is not backward compatible with JUnit 4, but the JUnit team created the JUnit Vintage Project to support JUnit 4 test cases on top of JUnit 5.


1 Answers

In general there is no need to modularize your test code (at least I can't think of a valid reason, maybe someone could give a satisfactory counter-example). Only one module-info.java file can (after all, it's not even required to modularize your main code) be present in your main code under src.

Since the module-info.java file will be only in your main source directory and not in the test source directory, then logically it should not depend on the JUnit module. So the questions now become how to compile and run the JUnit test classes by relying on the module (that represents the system under test) and the JUnit module.

To do that, you'll need to use the new options provided by the javac and java:

So assuming you have the following tree:

src
    module-info.java (declares a module called "my.module")
    mypackage
        MyClass.java
test_src
    mypackage
        MyClassTest.java
lib/junit-platform-console-standalone.jar

(note: specifically for JUnit 5, you can use the junit-platform-console-standalone artifact that contains the core JUnit engine and allows running tests in the console; see the user guide)

then you can compile the code as follows:

cd root_dir
javac -d mods/my.module src/module-info.java src/mypackage/MyClass.java

cd test_src
javac -d test_out --module-path ../mods;../lib/junit-platform-console-standalone.jar \
--add-modules org.junit.platform.console.standalone,my.module --patch-module my.module=. \
--add-reads my.module=org.junit.platform.console.standalone mypackage/MyClass.java

and you can run the compiled test class:

cd test_src/test_out
java --module-path=../../mods;../../lib/junit-platform-console-standalone.jar \
--add-modules my.module,org.junit.platform.console.standalone \
--add-reads my.module=org.junit.platform.console.standalone \
--patch-module my.module=. \
--add-opens my.module/test=org.junit.platform.console.standalone \ 
org.junit.platform.console.ConsoleLauncher test.MyClassTest

Awkward commands but that's the cost of not using Maven. I advise you to read about these options in the command documentation after understanding the concept of a module path. An important thing to note here are a couple of options:

--patch-module my.module=.

This is needed because the example test code has the same package (mypackage) as the module my.module. Without it, the module system will complain.

--add-reads my.module=org.junit.platform.console.standalone

This makes junit required by my.module even though it was not declared in module-info.java.

org.junit.platform.console.standalone is the name of the automatic module and is derived from the Jar manifest (as is the case with JUnit 5), otherwise from the name of the Jar file (e.g. in the case of JUnit 4).

Also note that this is what Maven probably does behind the scenes when compiling and running unit tests (see this issue for an equivalent plugin configuration that manually does the above).

What if for some reason, you also want to modularize your unit tests?

In this case, since in the example above the unit tests share the same package, you can include them in my.module and add a requirement to JUnit:

module my.module {
    exports mypackage;
    requires org.junit.platform.console.standalone;
}

If the unit tests were in a different package, you can also split them into two modules (two module-info.java), a my.module and a my.test.module where only the latter requires JUnit.

If you do include test classes in a module, then in the above commands, you don't need --add-reads and --patch-module.

like image 165
M A Avatar answered Oct 24 '22 01:10

M A