maven
multi-module
test-classes
module-sharing
java-development

Sharing src/test classes between modules in a multi-module maven project

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

In a multi-module Maven project, effective code sharing between modules is crucial for maintaining a clean, DRY (Don't Repeat Yourself) codebase. While sharing code in the src/main directory is relatively straightforward through dependencies, sharing code from src/test presents unique challenges and requires specific strategies.

Understanding the Structure

Maven multi-module projects often have the following structure:

 
1root-project
23├── module-a
4│   ├── src
5│   │   ├── main
6│   │   └── test
7│   └── pom.xml
89├── module-b
10│   ├── src
11│   │   ├── main
12│   │   └── test
13│   └── pom.xml
1415├── shared-test-resources
16│   ├── src
17│   │   ├── main
18│   │   └── test
19│   └── pom.xml
2021└── pom.xml

Goals of Sharing Test Code

  1. Avoid redundancy: Code reuse in test classes avoids redundancy across modules.
  2. Consistency: Ensures consistent testing standards and practices.
  3. Maintenance efficiency: Simplifies maintenance when alterations are necessary.

Approaches to Sharing Test Code

1. Using a Test Utility Module

The simplest approach is to create a separate module, such as shared-test-resources, specifically for shared test classes and utilities. This module will not produce deployable artifacts but instead function as a dependency for other modules' test scopes.

Key Implementations Steps:

  1. Configure the POM: Set up the shared-test-resources module with its own pom.xml. Make sure it is configured to create a JAR that can be used as a test dependency.
xml
1<!-- shared-test-resources/pom.xml -->
2<project>
3    <modelVersion>4.0.0</modelVersion>
4    <groupId>com.example</groupId>
5    <artifactId>shared-test-resources</artifactId>
6    <version>1.0-SNAPSHOT</version>
7    <packaging>jar</packaging>
8    
9    <build>
10        <plugins>
11            <plugin>
12                <groupId>org.apache.maven.plugins</groupId>
13                <artifactId>maven-jar-plugin</artifactId>
14                <version>3.2.0</version>
15                <configuration>
16                    <classifier>tests</classifier>
17                </configuration>
18            </plugin>
19        </plugins>
20    </build>
21</project>
  1. Include the Test Dependency: Set up each module (e.g., module-a, module-b) to utilize the shared-test-resources as a test dependency.
xml
1<!-- module-a/pom.xml -->
2<project>
3    <dependencies>
4        <dependency>
5            <groupId>com.example</groupId>
6            <artifactId>shared-test-resources</artifactId>
7            <version>1.0-SNAPSHOT</version>
8            <classifier>tests</classifier>
9            <scope>test</scope>
10        </dependency>
11    </dependencies>
12</project>

2. Leveraging Test Classpath

The test classpath can also be leveraged to share resources by placing shared test classes in the src/main directory of the shared-test-resources module. This allows these resources to be accessed during the test phase without explicitly adding them as part of a test resources artifact.

3. Using Source Sets

Although a bit more complex, customizing the lifecycle to include custom source sets can also be employed to handle test resource sharing by configuring specific plugins to manage test resource packaging and dependencies.

Considerations

  • Isolation: Shared test resources should usually be isolated from production code and kept in their relevant scope.
  • Build Times: Ensure that sharing test resources does not inadvertently increase build times or complicate module interdependencies.
  • Testing Framework Compatibility: Ensure compatibility with the testing frameworks being used in your modules.

Example Use Case

Suppose module-a and module-b both need access to a common DatabaseTestHelper class that simplifies database setups for testing. By placing this class in shared-test-resources, both modules can efficiently reuse the code:

java
1// shared-test-resources/src/main/java/com/example/testutils/DatabaseTestHelper.java
2package com.example.testutils;
3
4public class DatabaseTestHelper {
5    public static void setupDatabase() {
6        // Common database setup code
7    }
8}

Summary Table

AspectApproachDescription
Basic structureTest Utility ModuleCreate a module dedicated to shared test utilities.
Dependency setupConfigure scope and classifierDefine dependencies with test scope and attach proper classifiers.
Classpath sharingUse src/main for testsPlace shared test artifacts in src/main for inclusion in the test phase.
Complex setupsSource SetsManipulate the Maven build lifecycle with custom source sets if necessary.
AdvantagesReuse, Consistency, EfficiencyAvoid redundancy and maintain coherent testing standards.

By creating a well-structured sharing strategy, developers can significantly enhance the modularity and maintainability of multi-module Maven projects, especially concerning tests.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.