Maven test dependencies: how to get dependencies from sibling project into test scope of dependent project - maven

I have a multi-module maven project with the structure
main/
core/
interface/
where interface has a dependency on the artifact produced by core.
interface compiles, packages, and installs properly. However, when running tests in interface they fail due to not resolving dependencies found in core.
interface does not depend on the test classes themselves in core, simply compile scope maven dependencies defined in the core pom.xml file.
I did one painful attempt whereby I copied every single compile dependency declaration in core that was needed into the interface pom.xml and gave them all
<scope>test</scope>
. This helped with the tests but broke the install.
What is the best way to fix the dependency resolution of these tests in interface?
Here is an example of compile scope dependencies that are not resolved when running interface maven test goal.
core/pom.xml excerpt:
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${jsf-version}</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>${jsf-version}</version>
</dependency>
interface/pom.xml excerpt:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

Related

Why do test scope dependencies pull compile scope dependencies in Maven?

Currently my project uses spring boot starter test as so:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.3.8.RELEASE</version>
<scope>test</scope>
</dependency>
However, despite the test scope, it pulls in spring-core (which is a vulnerable tpl in this version) as a compile scope transitive dependency and it appears inside my compiled binary.
I'm aware that I can fix this by pulling spring-core explicitly with test scope:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.12.RELEASE</version>
<scope>test</scope>
</dependency>
However this shouldn't be necessary. Why is a dependency that's only available in tests pulling dependencies into the compile scope?
I double checked after the comment from J Fabian Meyer. While spring core was appearing under spring-boot-starter-test in the dependency tree, it was being pulled into the compile scope by spring-boot-starter-web.
My guess is spring-boot-starter-test pulls a later version of spring-core which is why it appeared in the tree as so

How to exclude tests maven dependency coming transitively

I got following scenario:
Project A has dependency on Project B (and its test classes, test classes are provided to A via classifier tag - tests in maven dependency)
Project A pom is as follows:
<dependency>
<groupId>sample.project</groupId>
<artifactId>project-B</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>sample.project</groupId>
<artifactId>project-B</artifactId>
<version>1.0</version>
<classifier>tests</classifier>
</dependency>
Now, I have got another project C, which depends on A. The problem is when I add dependency of Project A to C, I got Project B s tests jar transitively in Project C.
Project C pom is as follows:
<dependency>
<groupId>sample.project</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
</dependency>
How can I avoid just tests jar of Project B in C (not the normal jar of Project B in Project C)?
It is that I want to exclude tests jar of Project B from Project C.
Thanks
If a dependency is for tests only it should have the scope test:
<dependency>
<groupId>sample.project</groupId>
<artifactId>project-B</artifactId>
<version>1.0</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
Then it will not be transitively included into other projects.

dependency spring-boot-starter-test not inherited in multiple module maven project

In my multi-module maven project, all modules have a dependency of my own "common" module, eg, module "A" have this dependency "common". And the "common" module has a spring-boot-starter-test dependency. However, when I write unit test in this "A" module, it shows that the test dependency not imported. And then I check the dependencies and found that the spring-boot-starter-test is not imported. I want to ask why? In my sense, module "A" ref "common", "common" ref spring-boot-starter-test , so the module "A" should ref spring-boot-starter-test, but the fact is not that. By the way, in spite of this spring-boot-starter-test other dependencies works well via the hirachy. Does anyone know why it is? Thank you in advance.
Most likely in the module "A" dependecy spring-boot-starter-test has scope test. Dependecies with such scope is not transitive. See Dependency Scope section https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html.
The best solution is dependency management. See Dependency Management
Briefly, you need to create parrent module and declare dependency managment sectoin:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
Then inherit your modules from parent and just declare dependency without version and scope
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>A</artifactId>
</dependency>
</dependencies>

Dependencies in Dependency Management vs Dependencies in Maven versions plugin

When I use Maven versions:display-dependency-updates to check dependencies updates, I get two sections of result.
1st:
The following dependencies in Dependency Management have newer
versions:
2nd:
The following dependencies in Dependencies have newer versions:
What's the difference between these two?
The Dependency section of the POM defines the artifacts (jars, zip etc) upon which your project depends. i.e. the artifacts that it requires to compile, run etc.
The Dependency Management section of the POM is used to manage dependency information.
So for example, in the following pom the JUnit dependency is defined completely in the dependencyManagement section of the POM with version=4.11 and scope = test.
In the dependency section you simply need to define the JUnit dependency using the groupId and artifactId and maven automatically picks up the version and scope from the dependencyManagement section.
<?xml version="1.0" encoding="utf-8"?>
<project>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependencies>
</project>
Usually you would define the dependencyManagement section in a parent POM, where you define the version and scope for all dependencies. Then in the child module's you simply need to define the dependencies using the groupId and artifactId. This allows you to centrally manage versions and means you only have to update them in one place.
All of this is far better explained in the maven documentation:
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
The Versions Maven Plugin is simply listing the versions found in each of these sections, as it is possible in the dependencies section to override the version that was defined in the dependencyManagement section.

Maven 2 effective dependancies runtime and compile scope

What happen if I have in effective pom same dependency, but with different scopes: runtime and compile.?
For example,
<dependency>
<groupId>my_dep</groupId>
<artifactId>My_dep_subdata</artifactId>
<version>0.0.2</version>
<scope>runtime</scope>
</dependency>
....
<dependency>
<groupId>my_dep</groupId>
<artifactId>My_dep_subdata</artifactId>
<version>0.0.2</version>
<scope>compile</scope>
</dependency>
Which one will take place?
compile is available in all classpaths.
runtime is available in the runtime and test classpaths, but not the compile classpath.
I'd assume you will have the dependency on all classpaths (as in compile), but I have no idea why you would do something like that.

Resources