Maven2 Unit Test Dependencies
I’ve written a few utility classes for unit tests in one project and want to reuse these in the tests for another project. I’m too lazy to separate these out into a proper test-helper project and don’t want the tests to be in the main jar of the first project. The Maven2 docs aren’t very clear about how this can be achieved, but it is quite simple using test dependencies:
- In the first project, create a test-jar by adding the following to the
pom.xml:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <goals> <goal>test-jar</goal> </goals> </execution> </executions> </plugin> - Then in the second project add a dependency to that test jar by adding the tests classifier:
<dependency> <groupId>mygroup</groupId> <artifactId>myartifact</artifactId> <version>0.1-SNAPSHOT</version> <classifier>tests</classifier> <scope>test</scope> </dependency>
You’ll need a relatively recent version of maven for this to work - 2.0.7 definitely works, I think 2.0.5 onward should work but haven’t tested with these.
Hi,
It doesn’t work for me with multi-module project (have one parent project and poms for each module). Thanks
Tomas
What error do you get (class not found during test compilation, or a missing dependency error?). Is this an open source project with the sources available to inspect anywhere?
Also, which version of maven are you using?
Thanks a lot mate, it saved my day!!!
By the way, why are things so difficult with maven/maven2?
Yes, this is possible and usually works.
However, like many other things, possible is not always good, and in my opinion in this case it is not good.
On small, temporary projects, with just a few modules, it sometimes does not cause troubles.
But in projects with tens to hundreds of modules, and complex dependency graph, it drives you very quickly to the dependency hell, both at compile and test scope of dependencies.
This is because tests often have much more deps than you need for compiling; so it is easy to introduce circular dependencies. Such circles are sometimes even hard to detect without proper CI system.
Besides that, this approach makes you turn your test dependencies into compile scope, because the secondary artifact is not equipped with its own dependency set, and original test dependencies are never used for transitive closure of dependency graph.
For above reasons, I personally highly recommend to avoid this trick. I have long, long experience with many ways to dependency hell, and this one of them, proven. As you said, you were too lazy - that’s ok. But laziness of this sort on projects with some “future” is often/always far much more expensive than properly creating the helper project.
Petr: Thanks for the comment - learning from experienced users is always helpul.
I hadn’t considered the dependency issues before and now appreciate that they could cause problems. I still think using test dependencies may be ok in some limited circumstances, but in the future I will try to ensure that any generic test software is packaged as a separate module.
Mark: Thanks for this, it’s exactly what I was looking for (at least an hour has gone down the drain fiddling with a pair of pom.xml files and peering at the maven website to no avail).
I don’t really understand the danger of doing it as elucidated by Petr above; if it works like this, then why go to the trouble of creating a separate project just for test dependencies? That seems even more likely to cause needless complexity and possibly circular dependencies to me, e.g.:
Project A is required by Project B. However, some of A’s test code (a base utility class, say) is also required by B.
This test code also depends on some stuff in A.
So we have: A-test depends on A, B depends on A, B depends on A-test.
If we extract the A-test shared code into Project C, then we have:
C-test depends on A, B depends on A, B depends on C-test.
But any tests still in A that happen to use the code now moved to C (a reasonable assumption, since the shared test code in C was originally in A), then A-tests depend on C.
Thus, C depends on A, and A-tests depend on C. That kind of smells.