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

2

190

I have a multi-module Maven project. For the sake of this example, consider two modules:

  • data
  • consumer

Module consumer has module data as a dependency.

Module data declares a bunch of core classes. There are tests under src/test that use them. These tests require some long-winded object creation, so I have a class with some utility methods in it to create these objects. This utility class (SampleDataHelper) is in the src/test hierarchy.

I also have some tests in the consumer module that need to create some of these long-winded objects. I want to use my SampleDataHelper class (defined in data src/test) in tests that reside in my consumer src/test tree. Unfortunately, even though data is a dependency of consumer, consumer can't see the classes that exist under data src/test.

To combat this, I thought I might create another module (data-test), and move SampleDataHelper to it under src/main. Then I would include data-test as a test scope dependency of data. Unfortunately, this introduces a circular dependency: data uses data-test, but data-test also requires data.

The only solution I've come up with is to place SampleDataHelper under data src/main under a test package and hope that no real application code ever calls it.

How can I share my SampleDataHelper class between modules without putting it under src/main?

Clite answered 6/2, 2013 at 6:24 Comment(4)
Check out this answer. I think it should help you.Lander
For future readers: Maven Guide to using attached testsClite
@AndrewLogvinov: wouldn't your linked answer require a "two-step" build? To first build and deploy one module (data) before I can even compile my second module (consumer).Clite
I think you might come across some problems if you use mvn package, but it should work just fine in a single step build when you use mvn install or mvn deploy. Just a quick note. In one of our large projects we have a wrapper over junit's TestBase and it's located in src/main which I don't consider to be a good idea either.Lander
T
242

Your Consumer project depends upon your Data project, therefore we are happy that Data must be built prior to Consumer. As a result, using the techniques suggested in the comments, I would ensure your Data project contains all the test code that you wish to share and configure the POM to produce a test JAR:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.2</version>
  <executions>
    <execution>
      <goals>
        <goal>test-jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Your Consumer project would then depend upon both the normal Data JAR artifact, plus the additional test-jar artifact, with test scope of course:

<dependency>
  <groupId>com.foo</groupId>
  <artifactId>data</artifactId>
  <version>1.0</version>
  <type>test-jar</type>
  <scope>test</scope>
</dependency>

I've used this approach on many occasions and it works well.

Taluk answered 6/2, 2013 at 7:48 Comment(3)
regarding "Your Consumer project would then depend upon both the normal Data JAR artifact, plus the additional test-jar artifact" part, when I adding both the dependencies of data into consumer (let's say my artifacts named data & consumer as well) pom, without specific versions specification, the pom got error. Why is that happen?Yurev
@StasS probably best you open a separate question about that.Taluk
Did it :) #32120091Yurev
F
1

So the problem is that (some) tests in the data module depend on the SampleDataHelper class? You can move the SampleDataHelper class to src/main of the data-test module, if you at the same time move the tests (that depend on the specific class) to the src/test of the data-test module. Consequently, there would be no more circular dependencies.

Footrest answered 6/2, 2013 at 6:38 Comment(5)
If I understand you, you're suggesting that any tests that use SampleDataHelper be moved from either the data module or the consumer module (as appropriate) into data-test. Unfortunately I don't find this a very "neat" solution as it moves my tests out of the module they test, and into a different one. (Strictly speaking, you only said to move the data tests, but I think I'd find myself moving both for consistency). But thank you for your answer. :-)Clite
Yep, you understood me correctly. And arguably, it's more of a quick solution than a neat one. :-)Footrest
I would imagine the circular dependencies would remain. Assuming that the tests in question exercise the classes defined in the Data project, there would still need to be a reference back to the Data project from the Data-Test project.Taluk
@DuncanJones Sorry, there was a small typo in my post. The point I'm trying to make is that the data-test module should depend on the data module (and not the other way around). To avoid the circular dependency, all tests that currently reside in the data module that uses the SampleDataHelper must be moved to the data-test module.Footrest
Gotcha, that makes more sense.Taluk

© 2022 - 2024 — McMap. All rights reserved.