Using JUnit 5 with Java 9 without Maven or Gradle

ShadowDragon :

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?
M Anouti :

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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=433087&siteId=1