Let's say I have a Java project using Maven 3 and junit. There are src/main/java
and src/test/java
directories which contain main sources and test sources, respectively (everything is standard).
Now I want to migrate the project to Java 9. src/main/java
content represents Java 9 module; there is com/acme/project/module-info.java
looking approximately like this:
module com.acme.project { require module1; require module2; ... }
What if test code needs module-info.java
of its own? For example, to add a dependence on some module that is only needed for tests, not for production code. In such a case, I have to put module-info.java
to src/test/java/com/acme/project/
giving the module a different name. This way Maven seems to treat main sources and test sources as different modules, so I have to export packages from the main module to the test module, and require packages in the test module, something like this:
main module (in src/main/java/com/acme/project
):
module prod.module { exports com.acme.project to test.module; }
test module (in src/test/java/com/acme/project
):
module test.module { requires junit; requires prod.module; }
This produces
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project test-java9-modules-junit: Compilation failure: Compilation failure: [ERROR] /home/rpuch/git/my/test-java9-modules-junit/src/test/java/com/acme/project/GreeterTest.java:[1,1] package exists in another module: prod.module
because one package is defined in two modules. So now I have to have different projects in main module and test module, which is not convenient.
I feel I follow wrong path, it all starts looking very ugly. How can I have module-info.java
of its own in test code, or how do I achieve the same effects (require
, etc) without it?
you can run Junit 4 with Maven. You just need the Junit 4 dependency in your pom. You also need the surefire plugin to execute the tests. Hint: By default surefire looks for files with *Test.
Defining the Java 9 module. A module is a collection of code, data, and resources. It is a set of related packages and types (classes, abstract classes, interfaces, and more) with code, data files, and some static resources. For example, the module descriptor module-info.
JUnit is the testing framework that is extensively used for java projects built in the maven project format for unit testing purposes. Here we will see how we can mention the JUnit dependency in pom. xml file in a maven project and see various annotations and assert methods that can be used in java projects.
The module system does not distinguish between production code and test code, so if you choose to modularize test code, the prod.module
and the test.module
cannot share the same package com.acme.project
, as described in the specs:
Non-interference — The Java compiler, virtual machine, and run-time system must ensure that modules that contain packages of the same name do not interfere with each other. If two distinct modules contain packages of the same name then, from the perspective of each module, all of the types and members in that package are defined only by that module. Code in that package in one module must not be able to access package-private types or members in that package in the other module.
As indicated by Alan Bateman, the Maven compiler plugin uses --patch-module and other options provided by the module system when compiling code in the src/test/java tree, so that the module under test is augmented with the test classes. And this is also done by the Surefire plugin when running the test classes (see Support running unit tests in named Java 9 modules). This means you don't need to place your test code in a module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With