Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you organize tests in a modular Java project?

I am creating a modular build (using module-info.java) on GitHub, but when adding a module-info.java to the modules that I want modular, no tests can be executed...

How can I achieve this?

I am using the following versions:

  • junit.jupiter version 5.3.0 (first take was also unsuccessful with version 5.2.0)
  • maven-compiler-plugin version 3.8.0 (first take was also unsuccessful with version 3.7.0)
  • maven-surefire-plugin version 2.22.0 (first take was also unsuccessful with version 2.21.0)

A typical error from the failing tests looks like:

java.lang.reflect.InaccessibleObjectException: Unable to make com.github.jactor.rises.commons.dto.UserDtoTest() accessible: module jactor.rises.commons does not "opens com.github.jactor.rises.commons.dto" to unnamed module @65e98b1c

like image 458
jactor-rises Avatar asked Aug 31 '18 06:08

jactor-rises


Video Answer


2 Answers

Welcome to Testing In The Modular World!

Which kind of tests do you want write?

Extra-module tests: Create a test-only project (no "src/main" directory) and declare a "src/test/java/module-info.java" module descriptor.

In-module tests: As it was from Day 1 you need to "blend in"/merge/shadow your test classes into your main classes or vice versa. Here you have mainly two ways to achieve this:

  • "compile modular main sources" and "patch plain test sources" at test-runtime with some additional "JVM options hacking the Module system" to execute tests.
  • "compile modular test sources" and "patch modular main sources" at compile-time to execute tests.

Blog

https://sormuras.github.io/blog/2018-09-11-testing-in-the-modular-world

Examples

  • Work-in-progress blueprint https://github.com/sormuras/sandbox/tree/master/sors-modular-testing-blueprint

  • Integration tests starting with "modular-world-" at https://github.com/sormuras/junit-platform-maven-plugin/tree/master/src/it

Background and other resources

  • https://github.com/junit-team/junit5-samples/tree/master/junit5-modular-world
  • https://github.com/forax/pro
  • https://blog.codefx.org/java/five-command-line-options-to-hack-the-java-9-module-system/
like image 56
Sormuras Avatar answered Oct 20 '22 09:10

Sormuras


There is a (new) option in the Maven Surefire plugin called useModulePath. This option enables to use the traditional Java 8 class path instead of the module path and ignores a module-info.class from the main classes not turning on the Java module mode, i.e. all class on the calls path can be used.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        <!--  allow to use unnamed modules -->
        <useModulePath>false</useModulePath>
    </configuration>
</plugin>

That way the test sources can be kept as there were in Java 8. Only The main classes have to be modularized.

like image 36
k_o_ Avatar answered Oct 20 '22 09:10

k_o_