2016-12-19 74 views
3

我想开发一个Maven插件,并且测试它正确。我正在阅读关于maven-plugin-testing-harness的文档,并且已经尝试了几个小时。我经常碰到NoClassDefFoundErrorNoSuchMethodError,我只是无法弄清楚我需要哪些依赖关系。测试Maven插件与maven-plugin-testing-harness

这里是我的MCVE:

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

现在我越来越:

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 

这里是我的插件的pom.xml

<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很简单:

/** 
* 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 
    } 
} 

测试:

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进行测试:

<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> 

如果我改变maven-plugin-api3.0的版本,我得到:

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) 

我环顾四周,看到我全部人们似乎添加了一些随机的依赖关系,有时候事情有时不起作用。我花了几个小时试图做同样的事情,但没有设法使其工作。我现在非常绝望,希望有人最终能够明白,并指出我有正确的依赖关系和/或版本。

+0

你执行哪个Maven命令?我认为主要问题可能是2.0版本的maven-plugin-api依赖项,它似乎相当过时并且与其他依赖项不兼容...... –

+0

@FlorianAlbrecht'mvn clean install' – lexicore

+0

对不起,刚才读到你试过maven -plugin-api 3.0。但是你有没有试过3.3.9,和其他依赖相同的版本? –

回答

2

@FlorianAlbrecht是正确的,我必须指定相同版本(3.3.9)的Maven依赖关系。这是我结束了:

<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>