Maven - fieldenms/tg GitHub Wiki
This documents outlines guidelines for using Maven.
TLDR: If module X contains test classes that depend on another module Y and you want to use module
X in tests of module Z, create a separate module X-test.
Consider the following example:
- Module
Acontains test classes that use dependencyD. - Module
Bcontains tests that use test classes ofA.
For B to work, D must also be on its classpath at runtime.
If you want to limit B's access to test classes of A so that only tests of B can access it, you use:
-
testscope to ensure that the dependency is only available for the test compilation and execution phases -
test-jartype to indicate that you only need the "tests" part of the dependency
<!-- B -->
<dependency>
<groupId>example</groupId>
<artifactId>A</artifactId>
<scope>test</scope>
<type>test-jar</type>
</dependency>A problem will arise if A also uses test scope for D, which will make it unavailable for B at runtime.
There are a few ways to make D accessible to B at runtime:
- Declare dependency on
Ddirectly inB's POM. - Broaden the scope of
DinA's POM.
Approach 2 has the benefit of being simpler to maintain: B doesn't have to know about A's dependencies.
With this approach, A's POM contains the following:
<!-- A -->
<dependency>
<groupId>example</groupId>
<artifactId>D</artifactId>
</dependency>The default scope is compile, which is transitive.
This effectively establishes a relationship between B and D to be B -> A (test) -> D (compile),
which is equivalent to B -> D (test). Refer to the dependency scope matrix for details.
Had A declared test scope for D, it would not be visible to B, and ClassNotFoundException would
occur at runtime.
The only disadvantage of this approach is the reduced encapsulation: D becomes accessible to main
sources of A.
In general, it is better to extract reusable test classes into a separate module.
In the example above, we would extract reusable test classes of A into main sources of a new
module A-test and declare a dependency on D with scope compile. Then, B would depend on A-test
with scope test.
<!-- A-test -->
<dependency>
<groupId>example</groupId>
<artifactId>D</artifactId>
</dependency>
<!-- B -->
<dependency>
<groupId>example</groupId>
<artifactId>A-test</artifactId>
<scope>test</scope>
</dependency>References:
- POM Reference: Dependencies
- Dependency scopes - see the matrix of scopes.