Test Maven plugin with maven-plugin-testing-harnes

2019-05-12 00:58发布

I want to develop a Maven plugin and also test it properly. I was reading the documentation on maven-plugin-testing-harness and trying things out for a few hours already. I'm constantly running into NoClassDefFoundError and NoSuchMethodError, I just can't figure out which dependencies I need.

Here's my MCVE:

https://github.com/highsource/hello-maven-plugin

Right now I'm getting:

java.lang.NoClassDefFoundError: org/apache/maven/plugin/descriptor/PluginDescriptorBuilder
    at org.apache.maven.plugin.testing.AbstractMojoTestCase.setUp(AbstractMojoTestCase.java:161)
    at junit.framework.TestCase.runBare(TestCase.java:139)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at junit.framework.TestSuite.runTest(TestSuite.java:255)
    at junit.framework.TestSuite.run(TestSuite.java:250)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassNotFoundException: org.apache.maven.plugin.descriptor.PluginDescriptorBuilder
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 15 more

Here's the pom.xml of my plugin:

<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 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.hisrc.storyteller</groupId>
    <artifactId>storyteller-maven-plugin</artifactId>
    <packaging>maven-plugin</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>storyteller-maven-plugin Maven Mojo</name>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>3.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-artifact</artifactId>
            <version>3.3.9</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-compat</artifactId>
            <version>3.3.9</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-testing</groupId>
            <artifactId>maven-plugin-testing-harness</artifactId>
            <scope>test</scope>
            <version>3.3.0</version>
        </dependency>
    </dependencies>
</project>

MyMojo.java is trivial:

/**
 * Goal which touches a timestamp file.
 *
 * @goal touch
 * 
 * @phase process-sources
 */
public class MyMojo extends AbstractMojo {
    /**
     * Location of the file.
     * 
     * @parameter expression="${project.build.directory}"
     * @required
     */
    private File outputDirectory;

    public void execute() throws MojoExecutionException {
        // Simply creates a touch.txt file in outputDirectory
    }
}

The test:

public class MyMojoTest extends AbstractMojoTestCase {

    @Test
    public void testSomething()
        throws Exception
    {
        File pom = getTestFile( "src/test/resources/org/hisrc/storyteller/pom.xml" );
        assertNotNull( pom );
        assertTrue( pom.exists() );

        MyMojo myMojo = (MyMojo) lookupMojo( "touch", pom );
        assertNotNull( myMojo );
        myMojo.execute();
    }
}

pom.xml for the test:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.hisrc.storyteller</groupId>
    <artifactId>project-to-test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Test MyMojo</name>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>storyteller-maven-plugin</artifactId>
                <configuration>
                    <outputDirectory>target/test-harness/project-to-test</outputDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

If I change the version of the maven-plugin-api to 3.0, I'm getting:

java.lang.NoSuchMethodError: org.codehaus.plexus.ContainerConfiguration.setClassPathScanning(Ljava/lang/String;)Lorg/codehaus/plexus/ContainerConfiguration;
    at org.apache.maven.plugin.testing.AbstractMojoTestCase.setupContainerConfiguration(AbstractMojoTestCase.java:285)
    at org.apache.maven.plugin.testing.AbstractMojoTestCase.setupContainer(AbstractMojoTestCase.java:259)
    at org.apache.maven.plugin.testing.AbstractMojoTestCase.getContainer(AbstractMojoTestCase.java:298)
    at org.apache.maven.plugin.testing.AbstractMojoTestCase.setUp(AbstractMojoTestCase.java:152)
    at junit.framework.TestCase.runBare(TestCase.java:139)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at junit.framework.TestSuite.runTest(TestSuite.java:255)
    at junit.framework.TestSuite.run(TestSuite.java:250)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

I've looked around and all I see is that people seem to add some random dependencies, sometimes things work sometimes not. I've spent a few hours trying to do the same but did not manage to make it work. I'm quite desperate at the moment and hope that someone eventually figured it out and could point me to the correct dependencies and/or versions.

1条回答
够拽才男人
2楼-- · 2019-05-12 02:01

@FlorianAlbrecht was right, I had to specify the same version (3.3.9) for Maven dependencies. This is what I ended up with:

<properties>
    <maven.version>3.3.9</maven.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>${maven.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-core</artifactId>
        <version>${maven.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-artifact</artifactId>
        <version>${maven.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-compat</artifactId>
        <version>${maven.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.plugin-testing</groupId>
        <artifactId>maven-plugin-testing-harness</artifactId>
        <scope>test</scope>
        <version>3.3.0</version>
    </dependency>
</dependencies>
查看更多
登录 后发表回答