我想开发一个Maven插件,并且还要测试它。我正在阅读maven-plugin-testing-harness
上的文档并尝试了几个小时。我经常遇到NoClassDefFoundError
和NoSuchMethodError
,我无法弄清楚我需要哪些依赖项。
这是我的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-api
的版本更改为3.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 :(得分:2)
@FlorianAlbrecht是对的,我必须为Maven依赖项指定相同的版本(3.3.9
)。这就是我最终的结果:
<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>