Properly implementing Java modules in a Maven build with inter-module test dependencies
I have a multi-module project using Maven and Java. I am now trying to migrate to Java 9/10/11 and implement modules (as in JSR 376: Java Platform Module System, JPMS). As the project was already consisting of Maven modules, and the dependencies were straight, creating module descriptors for the project was quite straight forward.
Each Maven module now has their own module descriptor (module-info.java
), in the src/main/java
folder. There is no module descriptor for the test classes.
However, I stumbled upon a problem I have not been able to solve, and not found any descriptions on how to solve:
How can I have inter-module test dependencies with Maven and Java modules?
In my case, I have a "common" Maven module, which contains some interfaces and/or abstract classes (but no concrete implementation). In the same Maven module, I have abstract tests to ensure proper behavior for the implementation of these interfaces/abstract classes. Then, there are one or more sub modules, with implementations of the interface/abstract class and tests extending the abstract test.
However, when trying to execute the test
phase of the Maven build, the sub module will fail with:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:testCompile (default-testCompile) on project my-impl-module: Compilation failure: Compilation failure:
[ERROR] C:projectscom.examplemy-module-testmy-impl-modulesrctestjavacomexampleimplFooImplTest.java:[4,25] error: cannot find symbol
[ERROR] symbol: class FooAbstractTest
[ERROR] location: package com.example.common
I suspect that this happens because the tests are not part of the module. And even if Maven does some "magic" to get the tests executed within the scope of the module, it doesn't work for the tests in the module I depend on (for some reason). How do I fix this?
The structure of the project looks like this (full demo project files available here):
├───my-common-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───common
│ │ │ ├───AbstractFoo.java (abstract, implements Foo)
│ │ │ └───Foo.java (interface)
│ │ └───module-info.java (my.common.module: exports com.example.common)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───common
│ └───FooAbstractTest.java (abstract class, tests Foo)
├───my-impl-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───impl
│ │ │ └───FooImpl.java (extends AbstractFoo)
│ │ └───module-info.java (my.impl.module: requires my.common.module)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───impl
│ └───FooImplTest.java (extends FooAbstractTest)
└───pom.xml
Dependencies in the my-impl-module/pom.xml
is as follows:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<classifier>tests</classifier> <!-- tried type:test-jar instead, same error -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Note: The above is just a project I created to demonstrate the problem. The real project is a lot more complex, and found here (master branch is not modularized yet), but the principle is the same.
PS: I don't think there's anything wrong with the code itself, as everything compiles and runs using normal class path (ie. in IntelliJ, or Maven without the Java module descriptors). The problem is introduced with Java modules and the module path.
java maven junit module java-9
|
show 1 more comment
I have a multi-module project using Maven and Java. I am now trying to migrate to Java 9/10/11 and implement modules (as in JSR 376: Java Platform Module System, JPMS). As the project was already consisting of Maven modules, and the dependencies were straight, creating module descriptors for the project was quite straight forward.
Each Maven module now has their own module descriptor (module-info.java
), in the src/main/java
folder. There is no module descriptor for the test classes.
However, I stumbled upon a problem I have not been able to solve, and not found any descriptions on how to solve:
How can I have inter-module test dependencies with Maven and Java modules?
In my case, I have a "common" Maven module, which contains some interfaces and/or abstract classes (but no concrete implementation). In the same Maven module, I have abstract tests to ensure proper behavior for the implementation of these interfaces/abstract classes. Then, there are one or more sub modules, with implementations of the interface/abstract class and tests extending the abstract test.
However, when trying to execute the test
phase of the Maven build, the sub module will fail with:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:testCompile (default-testCompile) on project my-impl-module: Compilation failure: Compilation failure:
[ERROR] C:projectscom.examplemy-module-testmy-impl-modulesrctestjavacomexampleimplFooImplTest.java:[4,25] error: cannot find symbol
[ERROR] symbol: class FooAbstractTest
[ERROR] location: package com.example.common
I suspect that this happens because the tests are not part of the module. And even if Maven does some "magic" to get the tests executed within the scope of the module, it doesn't work for the tests in the module I depend on (for some reason). How do I fix this?
The structure of the project looks like this (full demo project files available here):
├───my-common-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───common
│ │ │ ├───AbstractFoo.java (abstract, implements Foo)
│ │ │ └───Foo.java (interface)
│ │ └───module-info.java (my.common.module: exports com.example.common)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───common
│ └───FooAbstractTest.java (abstract class, tests Foo)
├───my-impl-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───impl
│ │ │ └───FooImpl.java (extends AbstractFoo)
│ │ └───module-info.java (my.impl.module: requires my.common.module)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───impl
│ └───FooImplTest.java (extends FooAbstractTest)
└───pom.xml
Dependencies in the my-impl-module/pom.xml
is as follows:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<classifier>tests</classifier> <!-- tried type:test-jar instead, same error -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Note: The above is just a project I created to demonstrate the problem. The real project is a lot more complex, and found here (master branch is not modularized yet), but the principle is the same.
PS: I don't think there's anything wrong with the code itself, as everything compiles and runs using normal class path (ie. in IntelliJ, or Maven without the Java module descriptors). The problem is introduced with Java modules and the module path.
java maven junit module java-9
1
No doubts such questions would arise and a good read for them would be this answer by Sormuras which links to various useful links as well that can help you categorise your tests while working on modular projects.
– Naman
Nov 26 '18 at 10:22
1
Does this answer work for you? Summarising, add the goal test-jar to yourmy-common-module
and then change <classifier>tests</classifier> per <type>test-jar</type> in themy-impl-module/pom.xml
my-common-module dependency. I've tried and it works well.
– troig
Nov 26 '18 at 10:27
@troig Thanks. Did you try it with JPMS modules? I get the exact same problem usingtest-jar
dependency.
– haraldK
Nov 26 '18 at 10:49
1
@haraldK ,I only tried it with a multi-module maven project, but not JPMS. Sorry about that. I'll be waiing for other answers, good question!
– troig
Nov 26 '18 at 11:05
@nullpointer Interesting read, but I didn't really find a solution to my problem there... Do you have any suggestions? I'm doing white box testing, obviously.
– haraldK
Nov 26 '18 at 15:27
|
show 1 more comment
I have a multi-module project using Maven and Java. I am now trying to migrate to Java 9/10/11 and implement modules (as in JSR 376: Java Platform Module System, JPMS). As the project was already consisting of Maven modules, and the dependencies were straight, creating module descriptors for the project was quite straight forward.
Each Maven module now has their own module descriptor (module-info.java
), in the src/main/java
folder. There is no module descriptor for the test classes.
However, I stumbled upon a problem I have not been able to solve, and not found any descriptions on how to solve:
How can I have inter-module test dependencies with Maven and Java modules?
In my case, I have a "common" Maven module, which contains some interfaces and/or abstract classes (but no concrete implementation). In the same Maven module, I have abstract tests to ensure proper behavior for the implementation of these interfaces/abstract classes. Then, there are one or more sub modules, with implementations of the interface/abstract class and tests extending the abstract test.
However, when trying to execute the test
phase of the Maven build, the sub module will fail with:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:testCompile (default-testCompile) on project my-impl-module: Compilation failure: Compilation failure:
[ERROR] C:projectscom.examplemy-module-testmy-impl-modulesrctestjavacomexampleimplFooImplTest.java:[4,25] error: cannot find symbol
[ERROR] symbol: class FooAbstractTest
[ERROR] location: package com.example.common
I suspect that this happens because the tests are not part of the module. And even if Maven does some "magic" to get the tests executed within the scope of the module, it doesn't work for the tests in the module I depend on (for some reason). How do I fix this?
The structure of the project looks like this (full demo project files available here):
├───my-common-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───common
│ │ │ ├───AbstractFoo.java (abstract, implements Foo)
│ │ │ └───Foo.java (interface)
│ │ └───module-info.java (my.common.module: exports com.example.common)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───common
│ └───FooAbstractTest.java (abstract class, tests Foo)
├───my-impl-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───impl
│ │ │ └───FooImpl.java (extends AbstractFoo)
│ │ └───module-info.java (my.impl.module: requires my.common.module)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───impl
│ └───FooImplTest.java (extends FooAbstractTest)
└───pom.xml
Dependencies in the my-impl-module/pom.xml
is as follows:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<classifier>tests</classifier> <!-- tried type:test-jar instead, same error -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Note: The above is just a project I created to demonstrate the problem. The real project is a lot more complex, and found here (master branch is not modularized yet), but the principle is the same.
PS: I don't think there's anything wrong with the code itself, as everything compiles and runs using normal class path (ie. in IntelliJ, or Maven without the Java module descriptors). The problem is introduced with Java modules and the module path.
java maven junit module java-9
I have a multi-module project using Maven and Java. I am now trying to migrate to Java 9/10/11 and implement modules (as in JSR 376: Java Platform Module System, JPMS). As the project was already consisting of Maven modules, and the dependencies were straight, creating module descriptors for the project was quite straight forward.
Each Maven module now has their own module descriptor (module-info.java
), in the src/main/java
folder. There is no module descriptor for the test classes.
However, I stumbled upon a problem I have not been able to solve, and not found any descriptions on how to solve:
How can I have inter-module test dependencies with Maven and Java modules?
In my case, I have a "common" Maven module, which contains some interfaces and/or abstract classes (but no concrete implementation). In the same Maven module, I have abstract tests to ensure proper behavior for the implementation of these interfaces/abstract classes. Then, there are one or more sub modules, with implementations of the interface/abstract class and tests extending the abstract test.
However, when trying to execute the test
phase of the Maven build, the sub module will fail with:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:testCompile (default-testCompile) on project my-impl-module: Compilation failure: Compilation failure:
[ERROR] C:projectscom.examplemy-module-testmy-impl-modulesrctestjavacomexampleimplFooImplTest.java:[4,25] error: cannot find symbol
[ERROR] symbol: class FooAbstractTest
[ERROR] location: package com.example.common
I suspect that this happens because the tests are not part of the module. And even if Maven does some "magic" to get the tests executed within the scope of the module, it doesn't work for the tests in the module I depend on (for some reason). How do I fix this?
The structure of the project looks like this (full demo project files available here):
├───my-common-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───common
│ │ │ ├───AbstractFoo.java (abstract, implements Foo)
│ │ │ └───Foo.java (interface)
│ │ └───module-info.java (my.common.module: exports com.example.common)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───common
│ └───FooAbstractTest.java (abstract class, tests Foo)
├───my-impl-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───impl
│ │ │ └───FooImpl.java (extends AbstractFoo)
│ │ └───module-info.java (my.impl.module: requires my.common.module)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───impl
│ └───FooImplTest.java (extends FooAbstractTest)
└───pom.xml
Dependencies in the my-impl-module/pom.xml
is as follows:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<classifier>tests</classifier> <!-- tried type:test-jar instead, same error -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Note: The above is just a project I created to demonstrate the problem. The real project is a lot more complex, and found here (master branch is not modularized yet), but the principle is the same.
PS: I don't think there's anything wrong with the code itself, as everything compiles and runs using normal class path (ie. in IntelliJ, or Maven without the Java module descriptors). The problem is introduced with Java modules and the module path.
java maven junit module java-9
java maven junit module java-9
edited Dec 5 '18 at 14:54
haraldK
asked Nov 26 '18 at 9:03
haraldKharaldK
19.8k63581
19.8k63581
1
No doubts such questions would arise and a good read for them would be this answer by Sormuras which links to various useful links as well that can help you categorise your tests while working on modular projects.
– Naman
Nov 26 '18 at 10:22
1
Does this answer work for you? Summarising, add the goal test-jar to yourmy-common-module
and then change <classifier>tests</classifier> per <type>test-jar</type> in themy-impl-module/pom.xml
my-common-module dependency. I've tried and it works well.
– troig
Nov 26 '18 at 10:27
@troig Thanks. Did you try it with JPMS modules? I get the exact same problem usingtest-jar
dependency.
– haraldK
Nov 26 '18 at 10:49
1
@haraldK ,I only tried it with a multi-module maven project, but not JPMS. Sorry about that. I'll be waiing for other answers, good question!
– troig
Nov 26 '18 at 11:05
@nullpointer Interesting read, but I didn't really find a solution to my problem there... Do you have any suggestions? I'm doing white box testing, obviously.
– haraldK
Nov 26 '18 at 15:27
|
show 1 more comment
1
No doubts such questions would arise and a good read for them would be this answer by Sormuras which links to various useful links as well that can help you categorise your tests while working on modular projects.
– Naman
Nov 26 '18 at 10:22
1
Does this answer work for you? Summarising, add the goal test-jar to yourmy-common-module
and then change <classifier>tests</classifier> per <type>test-jar</type> in themy-impl-module/pom.xml
my-common-module dependency. I've tried and it works well.
– troig
Nov 26 '18 at 10:27
@troig Thanks. Did you try it with JPMS modules? I get the exact same problem usingtest-jar
dependency.
– haraldK
Nov 26 '18 at 10:49
1
@haraldK ,I only tried it with a multi-module maven project, but not JPMS. Sorry about that. I'll be waiing for other answers, good question!
– troig
Nov 26 '18 at 11:05
@nullpointer Interesting read, but I didn't really find a solution to my problem there... Do you have any suggestions? I'm doing white box testing, obviously.
– haraldK
Nov 26 '18 at 15:27
1
1
No doubts such questions would arise and a good read for them would be this answer by Sormuras which links to various useful links as well that can help you categorise your tests while working on modular projects.
– Naman
Nov 26 '18 at 10:22
No doubts such questions would arise and a good read for them would be this answer by Sormuras which links to various useful links as well that can help you categorise your tests while working on modular projects.
– Naman
Nov 26 '18 at 10:22
1
1
Does this answer work for you? Summarising, add the goal test-jar to your
my-common-module
and then change <classifier>tests</classifier> per <type>test-jar</type> in the my-impl-module/pom.xml
my-common-module dependency. I've tried and it works well.– troig
Nov 26 '18 at 10:27
Does this answer work for you? Summarising, add the goal test-jar to your
my-common-module
and then change <classifier>tests</classifier> per <type>test-jar</type> in the my-impl-module/pom.xml
my-common-module dependency. I've tried and it works well.– troig
Nov 26 '18 at 10:27
@troig Thanks. Did you try it with JPMS modules? I get the exact same problem using
test-jar
dependency.– haraldK
Nov 26 '18 at 10:49
@troig Thanks. Did you try it with JPMS modules? I get the exact same problem using
test-jar
dependency.– haraldK
Nov 26 '18 at 10:49
1
1
@haraldK ,I only tried it with a multi-module maven project, but not JPMS. Sorry about that. I'll be waiing for other answers, good question!
– troig
Nov 26 '18 at 11:05
@haraldK ,I only tried it with a multi-module maven project, but not JPMS. Sorry about that. I'll be waiing for other answers, good question!
– troig
Nov 26 '18 at 11:05
@nullpointer Interesting read, but I didn't really find a solution to my problem there... Do you have any suggestions? I'm doing white box testing, obviously.
– haraldK
Nov 26 '18 at 15:27
@nullpointer Interesting read, but I didn't really find a solution to my problem there... Do you have any suggestions? I'm doing white box testing, obviously.
– haraldK
Nov 26 '18 at 15:27
|
show 1 more comment
1 Answer
1
active
oldest
votes
Based on your demo project, I was able to duplicate your error. That said, here are the revised changes I made, after my first failed attempt, to be able to build the project:
I added the
maven-compiler-plugin
version 3.8.0 to all the modules. You need a version of 3.7 or higher to compile modules with Maven - at least that's the warning NetBeans showed. Since there is no harm, I added the pluging to both the common and implementation modules' POM files:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
I exported the test classes into their own
jar
file so they will be available to your implementation module or anyone for that matter. To do that, you need to add the following to yourmy-common-module/pom.xml
file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This will export
my-common-module
test classes into-tests.jar
file - i.e.my-common-module-1.0-SNAPSHOT-tests.jar
. Notice there is no need to add an execution for the regularjar
file as noted in this post. This will, however, introduced error that I will address next.
Rename your test package in
my-common-module
tocom.example.common.test
in order for the test classes to be loaded when compiling the implementation test class(es). This corrects the class load issue introduced when we exported the test classes with the same package name as in the module where the firstjar
, in this case the module, is loaded and the secondjar
, the test jar file, is ignored. Interesting enough, I'm concluding, based on observation, that the module path has higher precedence than the class path since the Maven compile parameters shows thetests.jar
is specified first in the class path. Runningmvn clean validate test -X
, we see compile parameters:
-d /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes -classpath /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT-tests.jar:/home/testenv/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/testenv/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar: --module-path /home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT.jar: -sourcepath /home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: -s /home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module example.implementation=/home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: --add-reads example.implementation=ALL-UNNAMED
We need to make the exported test classes available to the implementation module. Add this dependency to your
my-impl-module/pom.xml
:
<dependency>
<groupId>com.example</groupId>
<artifactId>Declaration</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Lastly in the
my-impl-module
test class, update the import to specify the new test package,com.example.common.text
, to access themy-common-module
test classes:
import com.example.declaration.test.AbstractFooTest;
import com.example.declaration.Foo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Test class inheriting from common module...
*/
public class FooImplementationTest extends AbstractFooTest { ... }
Here is the test results from my mvn clean package
of the new changes:
I updated my sample code in my java-cross-module-testing GitHub repo. The only lingering question I have, and I'm sure you do as well, is why did it worked when I defined the implementation module as a regular jar
project instead of a module. But that, I'll play with some other day. Hopefully what I provided solves your problem.
1
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have amodule-info.java
for "Implementation". When I add an appropriateImplementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"
– Coder Nr 23
Dec 6 '18 at 8:22
Thanks! As mentioned in the comments andpom.xml
extract, I have already tried thetest-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have amodule-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.
– haraldK
Dec 6 '18 at 8:40
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implementsFoo
(ie.DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).
– haraldK
Dec 7 '18 at 8:48
1
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
1
@haraldK, you're right! It's not adding the-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.
– Jose Henriquez
Dec 13 '18 at 6:00
|
show 10 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53477690%2fproperly-implementing-java-modules-in-a-maven-build-with-inter-module-test-depen%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Based on your demo project, I was able to duplicate your error. That said, here are the revised changes I made, after my first failed attempt, to be able to build the project:
I added the
maven-compiler-plugin
version 3.8.0 to all the modules. You need a version of 3.7 or higher to compile modules with Maven - at least that's the warning NetBeans showed. Since there is no harm, I added the pluging to both the common and implementation modules' POM files:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
I exported the test classes into their own
jar
file so they will be available to your implementation module or anyone for that matter. To do that, you need to add the following to yourmy-common-module/pom.xml
file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This will export
my-common-module
test classes into-tests.jar
file - i.e.my-common-module-1.0-SNAPSHOT-tests.jar
. Notice there is no need to add an execution for the regularjar
file as noted in this post. This will, however, introduced error that I will address next.
Rename your test package in
my-common-module
tocom.example.common.test
in order for the test classes to be loaded when compiling the implementation test class(es). This corrects the class load issue introduced when we exported the test classes with the same package name as in the module where the firstjar
, in this case the module, is loaded and the secondjar
, the test jar file, is ignored. Interesting enough, I'm concluding, based on observation, that the module path has higher precedence than the class path since the Maven compile parameters shows thetests.jar
is specified first in the class path. Runningmvn clean validate test -X
, we see compile parameters:
-d /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes -classpath /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT-tests.jar:/home/testenv/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/testenv/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar: --module-path /home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT.jar: -sourcepath /home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: -s /home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module example.implementation=/home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: --add-reads example.implementation=ALL-UNNAMED
We need to make the exported test classes available to the implementation module. Add this dependency to your
my-impl-module/pom.xml
:
<dependency>
<groupId>com.example</groupId>
<artifactId>Declaration</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Lastly in the
my-impl-module
test class, update the import to specify the new test package,com.example.common.text
, to access themy-common-module
test classes:
import com.example.declaration.test.AbstractFooTest;
import com.example.declaration.Foo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Test class inheriting from common module...
*/
public class FooImplementationTest extends AbstractFooTest { ... }
Here is the test results from my mvn clean package
of the new changes:
I updated my sample code in my java-cross-module-testing GitHub repo. The only lingering question I have, and I'm sure you do as well, is why did it worked when I defined the implementation module as a regular jar
project instead of a module. But that, I'll play with some other day. Hopefully what I provided solves your problem.
1
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have amodule-info.java
for "Implementation". When I add an appropriateImplementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"
– Coder Nr 23
Dec 6 '18 at 8:22
Thanks! As mentioned in the comments andpom.xml
extract, I have already tried thetest-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have amodule-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.
– haraldK
Dec 6 '18 at 8:40
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implementsFoo
(ie.DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).
– haraldK
Dec 7 '18 at 8:48
1
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
1
@haraldK, you're right! It's not adding the-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.
– Jose Henriquez
Dec 13 '18 at 6:00
|
show 10 more comments
Based on your demo project, I was able to duplicate your error. That said, here are the revised changes I made, after my first failed attempt, to be able to build the project:
I added the
maven-compiler-plugin
version 3.8.0 to all the modules. You need a version of 3.7 or higher to compile modules with Maven - at least that's the warning NetBeans showed. Since there is no harm, I added the pluging to both the common and implementation modules' POM files:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
I exported the test classes into their own
jar
file so they will be available to your implementation module or anyone for that matter. To do that, you need to add the following to yourmy-common-module/pom.xml
file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This will export
my-common-module
test classes into-tests.jar
file - i.e.my-common-module-1.0-SNAPSHOT-tests.jar
. Notice there is no need to add an execution for the regularjar
file as noted in this post. This will, however, introduced error that I will address next.
Rename your test package in
my-common-module
tocom.example.common.test
in order for the test classes to be loaded when compiling the implementation test class(es). This corrects the class load issue introduced when we exported the test classes with the same package name as in the module where the firstjar
, in this case the module, is loaded and the secondjar
, the test jar file, is ignored. Interesting enough, I'm concluding, based on observation, that the module path has higher precedence than the class path since the Maven compile parameters shows thetests.jar
is specified first in the class path. Runningmvn clean validate test -X
, we see compile parameters:
-d /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes -classpath /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT-tests.jar:/home/testenv/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/testenv/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar: --module-path /home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT.jar: -sourcepath /home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: -s /home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module example.implementation=/home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: --add-reads example.implementation=ALL-UNNAMED
We need to make the exported test classes available to the implementation module. Add this dependency to your
my-impl-module/pom.xml
:
<dependency>
<groupId>com.example</groupId>
<artifactId>Declaration</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Lastly in the
my-impl-module
test class, update the import to specify the new test package,com.example.common.text
, to access themy-common-module
test classes:
import com.example.declaration.test.AbstractFooTest;
import com.example.declaration.Foo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Test class inheriting from common module...
*/
public class FooImplementationTest extends AbstractFooTest { ... }
Here is the test results from my mvn clean package
of the new changes:
I updated my sample code in my java-cross-module-testing GitHub repo. The only lingering question I have, and I'm sure you do as well, is why did it worked when I defined the implementation module as a regular jar
project instead of a module. But that, I'll play with some other day. Hopefully what I provided solves your problem.
1
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have amodule-info.java
for "Implementation". When I add an appropriateImplementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"
– Coder Nr 23
Dec 6 '18 at 8:22
Thanks! As mentioned in the comments andpom.xml
extract, I have already tried thetest-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have amodule-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.
– haraldK
Dec 6 '18 at 8:40
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implementsFoo
(ie.DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).
– haraldK
Dec 7 '18 at 8:48
1
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
1
@haraldK, you're right! It's not adding the-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.
– Jose Henriquez
Dec 13 '18 at 6:00
|
show 10 more comments
Based on your demo project, I was able to duplicate your error. That said, here are the revised changes I made, after my first failed attempt, to be able to build the project:
I added the
maven-compiler-plugin
version 3.8.0 to all the modules. You need a version of 3.7 or higher to compile modules with Maven - at least that's the warning NetBeans showed. Since there is no harm, I added the pluging to both the common and implementation modules' POM files:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
I exported the test classes into their own
jar
file so they will be available to your implementation module or anyone for that matter. To do that, you need to add the following to yourmy-common-module/pom.xml
file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This will export
my-common-module
test classes into-tests.jar
file - i.e.my-common-module-1.0-SNAPSHOT-tests.jar
. Notice there is no need to add an execution for the regularjar
file as noted in this post. This will, however, introduced error that I will address next.
Rename your test package in
my-common-module
tocom.example.common.test
in order for the test classes to be loaded when compiling the implementation test class(es). This corrects the class load issue introduced when we exported the test classes with the same package name as in the module where the firstjar
, in this case the module, is loaded and the secondjar
, the test jar file, is ignored. Interesting enough, I'm concluding, based on observation, that the module path has higher precedence than the class path since the Maven compile parameters shows thetests.jar
is specified first in the class path. Runningmvn clean validate test -X
, we see compile parameters:
-d /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes -classpath /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT-tests.jar:/home/testenv/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/testenv/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar: --module-path /home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT.jar: -sourcepath /home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: -s /home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module example.implementation=/home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: --add-reads example.implementation=ALL-UNNAMED
We need to make the exported test classes available to the implementation module. Add this dependency to your
my-impl-module/pom.xml
:
<dependency>
<groupId>com.example</groupId>
<artifactId>Declaration</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Lastly in the
my-impl-module
test class, update the import to specify the new test package,com.example.common.text
, to access themy-common-module
test classes:
import com.example.declaration.test.AbstractFooTest;
import com.example.declaration.Foo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Test class inheriting from common module...
*/
public class FooImplementationTest extends AbstractFooTest { ... }
Here is the test results from my mvn clean package
of the new changes:
I updated my sample code in my java-cross-module-testing GitHub repo. The only lingering question I have, and I'm sure you do as well, is why did it worked when I defined the implementation module as a regular jar
project instead of a module. But that, I'll play with some other day. Hopefully what I provided solves your problem.
Based on your demo project, I was able to duplicate your error. That said, here are the revised changes I made, after my first failed attempt, to be able to build the project:
I added the
maven-compiler-plugin
version 3.8.0 to all the modules. You need a version of 3.7 or higher to compile modules with Maven - at least that's the warning NetBeans showed. Since there is no harm, I added the pluging to both the common and implementation modules' POM files:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
I exported the test classes into their own
jar
file so they will be available to your implementation module or anyone for that matter. To do that, you need to add the following to yourmy-common-module/pom.xml
file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This will export
my-common-module
test classes into-tests.jar
file - i.e.my-common-module-1.0-SNAPSHOT-tests.jar
. Notice there is no need to add an execution for the regularjar
file as noted in this post. This will, however, introduced error that I will address next.
Rename your test package in
my-common-module
tocom.example.common.test
in order for the test classes to be loaded when compiling the implementation test class(es). This corrects the class load issue introduced when we exported the test classes with the same package name as in the module where the firstjar
, in this case the module, is loaded and the secondjar
, the test jar file, is ignored. Interesting enough, I'm concluding, based on observation, that the module path has higher precedence than the class path since the Maven compile parameters shows thetests.jar
is specified first in the class path. Runningmvn clean validate test -X
, we see compile parameters:
-d /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes -classpath /home/testenv/NetBeansProjects/MavenProject/Implementation/target/test-classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT-tests.jar:/home/testenv/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/testenv/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar: --module-path /home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/.m2/repository/com/example/Declaration/1.0-SNAPSHOT/Declaration-1.0-SNAPSHOT.jar: -sourcepath /home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: -s /home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module example.implementation=/home/testenv/NetBeansProjects/MavenProject/Implementation/target/classes:/home/testenv/NetBeansProjects/MavenProject/Implementation/src/test/java:/home/testenv/NetBeansProjects/MavenProject/Implementation/target/generated-test-sources/test-annotations: --add-reads example.implementation=ALL-UNNAMED
We need to make the exported test classes available to the implementation module. Add this dependency to your
my-impl-module/pom.xml
:
<dependency>
<groupId>com.example</groupId>
<artifactId>Declaration</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Lastly in the
my-impl-module
test class, update the import to specify the new test package,com.example.common.text
, to access themy-common-module
test classes:
import com.example.declaration.test.AbstractFooTest;
import com.example.declaration.Foo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Test class inheriting from common module...
*/
public class FooImplementationTest extends AbstractFooTest { ... }
Here is the test results from my mvn clean package
of the new changes:
I updated my sample code in my java-cross-module-testing GitHub repo. The only lingering question I have, and I'm sure you do as well, is why did it worked when I defined the implementation module as a regular jar
project instead of a module. But that, I'll play with some other day. Hopefully what I provided solves your problem.
edited Dec 7 '18 at 6:01
answered Dec 6 '18 at 4:44
Jose HenriquezJose Henriquez
1765
1765
1
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have amodule-info.java
for "Implementation". When I add an appropriateImplementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"
– Coder Nr 23
Dec 6 '18 at 8:22
Thanks! As mentioned in the comments andpom.xml
extract, I have already tried thetest-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have amodule-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.
– haraldK
Dec 6 '18 at 8:40
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implementsFoo
(ie.DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).
– haraldK
Dec 7 '18 at 8:48
1
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
1
@haraldK, you're right! It's not adding the-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.
– Jose Henriquez
Dec 13 '18 at 6:00
|
show 10 more comments
1
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have amodule-info.java
for "Implementation". When I add an appropriateImplementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"
– Coder Nr 23
Dec 6 '18 at 8:22
Thanks! As mentioned in the comments andpom.xml
extract, I have already tried thetest-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have amodule-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.
– haraldK
Dec 6 '18 at 8:40
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implementsFoo
(ie.DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).
– haraldK
Dec 7 '18 at 8:48
1
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
1
@haraldK, you're right! It's not adding the-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.
– Jose Henriquez
Dec 13 '18 at 6:00
1
1
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have a
module-info.java
for "Implementation". When I add an appropriate Implementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"– Coder Nr 23
Dec 6 '18 at 8:22
Thanks to give this a try, but it seems this doesn't solve not the exact problem haraldK described. It doesn't fully use JPMS: Your example project doesn't have a
module-info.java
for "Implementation". When I add an appropriate Implementation/src/main/java/module-info.java
, it fails with: "module not found: com.example.declaration"– Coder Nr 23
Dec 6 '18 at 8:22
Thanks! As mentioned in the comments and
pom.xml
extract, I have already tried the test-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have a module-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.– haraldK
Dec 6 '18 at 8:40
Thanks! As mentioned in the comments and
pom.xml
extract, I have already tried the test-jar
approach. It works fine without JPMS modules. But it gives exactly the same error when you add them, unfortunately. What makes your project work is the fact that you don't have a module-info.java
in your "Implementation" module, as @CoderNr23 points out. That is not a solution, sorry.– haraldK
Dec 6 '18 at 8:40
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implements
Foo
(ie. DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).– haraldK
Dec 7 '18 at 8:48
I appreciate the effort! The updated answer does make the test project build, but it completely sidesteps the problem. Unfortunately, I can't change the package name of the tests as you do in step 3. In the real project I refer to, I have package scoped classes that implements
Foo
(ie. DefaultFoo
) here that I need to test. This also means that introducing a separate module for the abstract tests only, will not work (would cause circular dependency, or require duplicated test code).– haraldK
Dec 7 '18 at 8:48
1
1
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
Ok, so in conclusion: you can only get a test-jar dependency to work if the tests are in seperate packages. For a case with complex "white box testing", that will not be a good solution. But for most other cases (including mine), that's probably an acceptable workaround.
– Coder Nr 23
Dec 12 '18 at 7:33
1
1
@haraldK, you're right! It's not adding the
-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.– Jose Henriquez
Dec 13 '18 at 6:00
@haraldK, you're right! It's not adding the
-tests-jar
file when running tests. I tried with a period and a hyphen with the same results. My hunch is that Maven doesn't find the file because those "special" characters in the jar file name is breaking the parsing logic when looking for the string "-tests-jar". I got the same error when I created a new project from scratch - just in case I messed up in renaming the Maven modules. Definitely a Maven bug.– Jose Henriquez
Dec 13 '18 at 6:00
|
show 10 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53477690%2fproperly-implementing-java-modules-in-a-maven-build-with-inter-module-test-depen%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
No doubts such questions would arise and a good read for them would be this answer by Sormuras which links to various useful links as well that can help you categorise your tests while working on modular projects.
– Naman
Nov 26 '18 at 10:22
1
Does this answer work for you? Summarising, add the goal test-jar to your
my-common-module
and then change <classifier>tests</classifier> per <type>test-jar</type> in themy-impl-module/pom.xml
my-common-module dependency. I've tried and it works well.– troig
Nov 26 '18 at 10:27
@troig Thanks. Did you try it with JPMS modules? I get the exact same problem using
test-jar
dependency.– haraldK
Nov 26 '18 at 10:49
1
@haraldK ,I only tried it with a multi-module maven project, but not JPMS. Sorry about that. I'll be waiing for other answers, good question!
– troig
Nov 26 '18 at 11:05
@nullpointer Interesting read, but I didn't really find a solution to my problem there... Do you have any suggestions? I'm doing white box testing, obviously.
– haraldK
Nov 26 '18 at 15:27