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
A
contains test classes that use dependencyD
. - Module
B
contains 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:
-
test
scope to ensure that the dependency is only available for the test compilation and execution phases -
test-jar
type 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
D
directly inB
's POM. - Broaden the scope of
D
inA
'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.