1

There are two independent Maven projects. There isn't neither common parent nor aggregator POM files.

The second project needs some classes provided by shared-tests. More precisely I'd re-use some common test cases in dependent project and run them during test and integration-test phases.

The first project (shared-tests) contains some shared test cases.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.github.zforgo.stackoverflow</groupId>
    <artifactId>shared-tests</artifactId>
    <version>0.1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.release>11</maven.compiler.release>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

After running

mvn clean install

the test jar has stored alongside production jar.

spinner@zaphod:~/.m2/repository/io/github/zforgo/stackoverflow/shared-tests/0.1.0-SNAPSHOT$ ll
total 28
drwxrwxr-x 2 spinner spinner 4096 Dec 20 15:16 ./
drwxrwxr-x 3 spinner spinner 4096 Dec 20 15:16 ../
-rw-rw-r-- 1 spinner spinner  931 Dec 20 15:23 maven-metadata-local.xml
-rw-rw-r-- 1 spinner spinner  248 Dec 20 15:23 _remote.repositories
-rw-rw-r-- 1 spinner spinner 3183 Dec 20 15:23 shared-tests-0.1.0-SNAPSHOT.jar
-rw-rw-r-- 1 spinner spinner 3299 Dec 20 14:41 shared-tests-0.1.0-SNAPSHOT.pom
-rw-rw-r-- 1 spinner spinner 3961 Dec 20 15:23 shared-tests-0.1.0-SNAPSHOT-tests.jar

The second project defines the shared-tests as a test-scoped dependency and during generate-test-sources phase it tries to unpack.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.github.zforgo.stackoverflow</groupId>
    <artifactId>project</artifactId>
    <version>0.1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>io.github.zforgo.stackoverflow</groupId>
            <artifactId>shared-tests</artifactId>
            <version>0.1.0-SNAPSHOT</version>
            <type>test-jar</type>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.2</version>
                <executions>
                    <execution>
                        <id>share-tests</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>io.github.zforgo.stackoverflow</groupId>
                                    <artifactId>shared-tests</artifactId>
                                    <version>0.1.0-SNAPSHOT</version>
                                    <type>test-jar</type>
                                    <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

But when I run

mvn install

the production artifact of shared-tests will be unpacked instead of test-jar.

[INFO] ---------------< io.github.zforgo.stackoverflow:project >---------------
[INFO] Building project 0.1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.1.2:unpack (share-tests) @ project ---
[INFO] Configured Artifact: io.github.zforgo.stackoverflow:shared-tests:0.1.0-SNAPSHOT:test-jar
[INFO] Unpacking /home/spinner/.m2/repository/io/github/zforgo/stackoverflow/shared-tests/0.1.0-SNAPSHOT/shared-tests-0.1.0-SNAPSHOT.jar to /work/source/stackoverflow/junit-test-sharing/test-jar/project/target/alternateLocation with includes "" and excludes ""
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Based on the logs the desired artifact has been configured

Configured Artifact: io.github.zforgo.stackoverflow:shared-tests:0.1.0-SNAPSHOT:test-jar

but the wrong one was unpacked.

Unpacking [...]/shared-tests/0.1.0-SNAPSHOT/shared-tests-0.1.0-SNAPSHOT.jar to ...

Is this a bug or is there any possibility to unpack test-jar into an other project? Probably using <classifier/> can be a solution but that is not made to specify type of an artifact.

zforgo
  • 2,508
  • 2
  • 14
  • 22
  • Wrong way. Just define in the second project a dependency with the appropriate classifier see https://maven.apache.org/plugins/maven-jar-plugin/examples/create-test-jar.html no need to use dependency:unpack... – khmarbaise Dec 20 '20 at 15:32
  • @khmarbaise thanks for the hint but as far as I know it isn't enough for me. That definition just allow to use (e.g. import or extend) artifact's classes but I'd like to re-run those unpacked test cases in the dependent module. – zforgo Dec 20 '20 at 15:40
  • 1
    If you have two independent Maven projects but reuse tests it sounds like they belong together in a multi module build or you have to change the tests how they work. The problem as unit tests are run is that they are searched and executed within the current module. To solve your problem you have to configure https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#dependenciesToScan to scan for tests on dependencies... and keep the test-jar setup as I described... – khmarbaise Dec 20 '20 at 16:00
  • Apart from that if you have the same test that means very likely you have the same functionality which means you could refactor out the code from the two projects... and result would be having only a single set of tests. – khmarbaise Dec 20 '20 at 16:10
  • At first thank you very much ```dependenciesToScan``` hint. Hopefully it wil help. I'm just looking for possibilites to improve our test coverage. Sometimes it can be useful. E.g. an integration test which checks the monitoring endpoint exists and so on. Fortunately maven-failsafe-plugin is also able to scan dependencies. You're totally rigth, almost everytime refactoring is the real solution but sometimes shared test is an opportunity. Tanks again. – zforgo Dec 20 '20 at 16:28

1 Answers1

1

After some debugging it seems this is a bug.

The unpack goal reads configuration well and creates an ArtifactItem object with the right parameters. But when it creates an Artifact object based on ArtifactItem the type parameter wasn't set and the default value (jar) will used.

Source code can be found here.

Related part is:

   protected Artifact getArtifact( ArtifactItem artifactItem )
        throws MojoExecutionException
    {
        Artifact artifact;

        try
        {

            // ...

            ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest();

            if ( localRepositoryDirectory != null )
            {
                buildingRequest =
                    repositoryManager.setLocalRepositoryBasedir( buildingRequest, localRepositoryDirectory );
            }

            // Map dependency to artifact coordinate
            DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
            coordinate.setGroupId( artifactItem.getGroupId() );
            coordinate.setArtifactId( artifactItem.getArtifactId() );
            coordinate.setVersion( artifactItem.getVersion() );
            coordinate.setClassifier( artifactItem.getClassifier() );

            // ...


            artifact = artifactResolver.resolveArtifact( buildingRequest, coordinate ).getArtifact();
        }
        catch ( ArtifactResolverException e )
        {
            throw new MojoExecutionException( "Unable to find/resolve artifact.", e );
        }

        return artifact;
    }

While the

            // Map dependency to artifact coordinate
            DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();

sets type to java as a default value it never updated. This behaviour reported here: MDEP-732

Workaround can be using <classifier> instead of <type> like:

<!-- ... -->
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>io.github.zforgo.stackoverflow</groupId>
                                    <artifactId>shared-tests</artifactId>
                                    <version>0.1.0-SNAPSHOT</version>
                                    <!-- note: classifier must be tests not test-jar -->
                                    <classifier>tests</classifier>
                                    <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
<!-- ... -->
zforgo
  • 2,508
  • 2
  • 14
  • 22