So I have some classes in a module I wrote to help with Robolectric style unit tests, and I want to be able to share this module in a bunch of my other modules. This module has unit tests of its own, and I have set it up as an apklib. I’m using the maven-android-plugin. The problem seems to be that it doesn’t recognize apklibs in the test scope. Are there any workarounds for this, or am I missing something?
One thing I’m noticing is if I run the command mvn install, everything builds and all my tests run fine, but if I do mvn test it says it can’t find classes.
Maven has this concept of “the reactor”, which is just a fancy term for the list of projects being built. At the start of a Maven build, and at the end, Maven prints out this list of projects (using
/project/name(XPath) if defined orgroupId:artifactIdotherwise).For each project in the reactor, Maven maintains a list of artifacts that have been attached. By default, each module’s
pom.xmlis attached, and as each plugin runs, they have the option of attaching additional artifacts. Most plugins do not attach artifacts, here are some plugins that do:jar:jarcreates a.jarand attaches it as the primary artifact (unless you specify a classifier in the configuration)war:warcreates a.warand attaches itsource:jarcreates a.jarof the source Java code and attaches it with a classifier ofsourcejavadoc:jarcreates a.jarof the JavaDocs and attaches it with a classifier ofjavadocandroid:apklibcreates a.apklibartifact and attaches it as the primary artifactThere is also a default primary artifact (this is the one that gets replaced by jar:jar) which is actually a directory and not a file, as such it will not get installed or deployed to the local repository cache or a remote repository.
So when in the reactor, and a plugin that attaches the primary artifact has not run yet (in your case
android:apklib), and another plugin asks for the primary artifact, it will be given the directory${project.build.outputDirectory}. If after the primary artifact as been attached, then that primary artifact will be provided.The
testphase happens before thepackagephase, so will pass the the directory and not the.apklib.Things get more complex in a multi-module project (which is where my long intro should help you out)
Maven has to build the test classpath. If one of the dependencies is within the reactor, Maven will use the artifact attached to the reactor. Otherwise it will use the local cache (populating from the remote repositories if necessary).
When you run
In a multimdule project from the root, there is no replacement of the default (directory-based) artifact, so intra-module classpath will be to the target/classes directories (and we are assuming that the android plugin knows how to handle such tests… you have found that it doesn’t).
When you run
or
In the same project, however, because each module completes its life cycle sequentially, all the dependent modules will have swapped in their
.apklibfiles as their attached artifact.Most likely the issue here is that your tests won’t work with a directory and need the actual
.apklibfile. in which case you have no choice but to push the lifecycle to at least thepackagephase.