我正在尝试使用maven plugin testing harness测试我的maven插件。我能找到的关于这个问题的唯一文档是相当陈旧的,我发现similar个线程有相同的错误,但没有解决方案,至少没有解决问题的方法。在尝试运行 lookupMojo 方法时,错误可以归结为 NoSuchElementException 。
是否有其他人遇到此问题或类似问题,您是如何解决的?如果您需要更多信息,请告诉我,我会发布更新。
插件类
@Mojo(name = "my_plugin", defaultPhase = LifecyclePhase.CLEAN, threadSafe = true)
public class MyPlugin extends AbstractMojo
{
private static final Logger logger = LoggerFactory.getLogger(MyPlugin.class);
@Parameter private String configFileLocation;
public void execute() throws MojoExecutionException, MojoFailureException
{
logger.info("The config file location is: {}", configFileLocation);
saveSystemProperties(new File(configFileLocation));
}
private void saveSystemProperties(final File file)
{
logger.info("Attempting to save system properties");
try(FileOutputStream fr = new FileOutputStream(file))
{
System.getProperties().store(fr, "Properties");
logger.info("Properties successfully saved. Closing File Output Stream Implicitly");
}
catch(IOException e)
{
logger.info("There was an IO error. ");
e.printStackTrace();
}
}
}
插件测试类
public class MyPluginTester extends AbstractMojoTestCase
{
private static final Logger logger = LoggerFactory.getLogger(MyPluginTester.class);
protected void setup() throws Exception
{
super.setUp();
}
protected void tearDown() throws Exception
{
super.tearDown();
}
public void testMojoGoal() throws Exception
{
logger.info("Loading Test Pom File");
File testPom = new File(getBasedir(),"src/test/resources/pom/basic-test-plugin-config.xml");
assertNotNull(testPom);
MyPlugin mojo = (LittleSysStore)lookupMojo("configure", testPom);
assertNotNull(mojo);
}
}
POM文件
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.my.stuff</groupId>
<artifactId>my-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<properties>
<maven.plugin.annotations.version>3.5</maven.plugin.annotations.version>
<maven.plugin.testing.version>3.3.0</maven.plugin.testing.version>
<maven.version>3.5.0</maven.version>
<slf4j.version>1.7.25</slf4j.version>
<junit.version>4.12</junit.version>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${maven.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>${maven.plugin.annotations.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>${maven.plugin.testing.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
输出
org.codehaus.plexus.component.repository.exception.ComponentLookupException: java.util.NoSuchElementException
role: org.apache.maven.plugin.Mojo
roleHint: com.my.stuff-maven-plugin:1.0-SNAPSHOT:clean
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:267)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:243)
at org.codehaus.plexus.PlexusTestCase.lookup(PlexusTestCase.java:205)
at org.apache.maven.plugin.testing.AbstractMojoTestCase.lookupMojo(AbstractMojoTestCase.java:410)
at org.apache.maven.plugin.testing.AbstractMojoTestCase.lookupMojo(AbstractMojoTestCase.java:355)
at unit_tests.LittleSysStoreTest.testMojoGoal(LittleSysStoreTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at junit.framework.TestCase.runTest(TestCase.java:176)
at junit.framework.TestCase.runBare(TestCase.java:141)
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:252)
at junit.framework.TestSuite.run(TestSuite.java:247)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.util.NoSuchElementException
at java.util.Collections$EmptyIterator.next(Collections.java:4189)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:263)
... 23 more
答案 0 :(得分:7)
浪费了一个小时阅读他们可怕的文档,我看了一下线束测试套件。请尝试使用以下内容:
void testStuff() throws Exception {
File testPom = new File(getBasedir(),"src/test/resources/pom/basic-test-plugin-config.xml");
assertNotNull(testPom);
MyPlugin mojo = new MyPlugin();
mojo = (MyPlugin) configureMojo(
mojo, extractPluginConfiguration("cue-maven-plugin", testPom
);
mojo.execute();
}
像魅力一样工作。
答案 1 :(得分:0)
我创建了以下 maven-plugin
项目,该项目成功运行名为 testLiveWithPOM()
的“unitegration”测试(即使用来自本地 Maven 存储库的实时插件解析的 Surefire/JUnit 测试)。关键思想是抑制 Surefire 的 <execution>/<id>default-test
并在 <default-install>
之后使用 maven-invoker
运行它。也许这也可以通过 Maven Invoker Plugin 实现。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>igb</groupId>
<artifactId>my-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<name>My Maven Plugin with Surefire tests</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>11</maven.compiler.release>
<maven.version>3.6.3</maven.version>
</properties>
<prerequisites>
<maven>${maven.version}</maven>
</prerequisites>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<!-- needed when injecting the Maven Project into a plugin -->
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<!--
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${maven.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-invoker</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!-- use latest plugins rather than Maven's defaults -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_maven-plugin_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<!-- From: How to override default binding to phase of a Maven plugin <https://stackoverflow.com/q/13250377/1744774> -->
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<!--
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
<version>3.2.1</version>
</plugin>
-->
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<executions>
<execution>
<id>generate-help-mojo</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!-- From: How to override default binding to phase of a Maven plugin <https://stackoverflow.com/q/13250377/1744774> -->
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>test-after-install</id>
<phase>install</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package name.broser.gerold.maven.plugins;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
@Mojo( name = "validate", defaultPhase = LifecyclePhase.VALIDATE )
public class ValidateMojo extends AbstractMojo {
private final Log log = getLog();
@Parameter( defaultValue = "${project}", readonly = true )
private MavenProject project;
@Parameter
private String message;
@Override
public void execute() throws MojoExecutionException {
log.debug( "message:\n " + message + ".execute()..." );
log.debug( "project:\n " + project );
} // execute()
} // ValidateMojo
package name.broser.gerold.maven.plugins;
import static java.lang.System.out;
import java.nio.file.Path;
import java.util.List;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.MavenInvocationException;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ValidateMojoTest extends AbstractMojoTestCase {
private final Logger log = LoggerFactory.getLogger( ValidateMojoTest.class );
private final Path pom = Path.of( getBasedir(), "src/test/resources/my-maven-plugin-test/pom.xml" );
@Test
public void testPOM() throws Exception {
log.debug( "\n Using POM '...{}'.", pom.toString().substring( getBasedir().length() ) );
assertNotNull( pom );
assertTrue( pom.toFile().exists() );
}
@Test
public void testLiveWithPOM() throws Exception {
log.debug( "\n Live testing my plugin's validate goal ..." );
out.println( new String( new char[80] ).replace( "\0", "#" ) );
final InvocationResult result = MavenInvoker.invoke( pom, List.of( "validate" ) /*, Debug.TRUE*/ );
out.println( new String( new char[80] ).replace( "\0", "#" ) );
if ( result.getExitCode() != 0 )
throw new MavenInvocationException(
String.format( "MavenInvoker.invoke() failed with exit code %n.", result.getExitCode() ),
result.getExecutionException() );
}
} // ValidateMojoTest
package name.broser.gerold.maven.plugins;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Properties;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.MavenInvocationException;
/** A helper class to invoke Maven. Handy for testing self-written plugins.
*
* @author Gerold "Geri" Broser <https://stackoverflow.com/users/1744774/gerold-broser>
*/
public class MavenInvoker {
public enum Debug {
FALSE( false ),
TRUE( true );
private final boolean debug;
Debug( final boolean debug ) {
this.debug = debug;
}
boolean value() {
return debug;
}
} // Debug
/**
* @param pom The POM to be used when invoking Maven.
* @param phasesAndGoals The lifecycle phases and plugin goals to invoke. See <a href="https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#lifecycle-reference">Lifecycle Reference</a>.
* @param debug Optional parameter. Default: {@link Debug}{@code .FALSE}. Set it to {@link Debug}{@code .TRUE} to run Maven in debug mode (like {@code mvn -X ...}).
* @return The {@link InvocationResult} of the invocation.
* @throws MavenInvocationException
* @throws IOException
*/
public static InvocationResult invoke( final Path pom, final List<String> phasesAndGoals, final Debug... debug )
throws MavenInvocationException, IOException {
return invoke( pom, phasesAndGoals, System.getProperties(), debug );
} // invoke()
/**
* @param pom The POM to be used when invoking Maven.
* @param phasesAndGoals The lifecycle phases and plugin goals to invoke. See <a href="https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#lifecycle-reference">Lifecycle Reference</a>.
* @param properties Unused yet, since it causes a message "The command line is too long.".
* @param debug Optional parameter. Default: {@link Debug}{@code .FALSE}. Set it to {@link Debug}{@code .TRUE} to run Maven in debug mode (like {@code mvn -X ...}).
* @return The {@link InvocationResult} of the invocation.
* @throws MavenInvocationException
* @throws IOException
*/
public static InvocationResult invoke( final Path pom, final List<String> phasesAndGoals, final Properties properties,
final Debug... debug )
throws MavenInvocationException, IOException {
// From: How to run Maven from Java? <https://stackoverflow.com/a/21534306/1744774>
final InvocationRequest request = new DefaultInvocationRequest()
.setPomFile( pom.toFile() )
.setGoals( phasesAndGoals )
.setDebug( debug.length > 0 ? debug[0].value() : false )
.setBatchMode( true );
//.setProperties( properties ); // Causes message: "The command line is too long." (?!?)
// Not necessary here since ignored with Batch Mode.
//From: How to solve Maven Invoker API warning: Maven will be executed in interactive mode, but no input stream has been configured
// <https://stackoverflow.com/a/60803155/1744774>
//try ( InputStream nis = InputStream.nullInputStream() ) {
// request.setInputStream( nis );
//}
return new DefaultInvoker().execute( request );
} // invoke()
} // MavenInvoker
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>igb</groupId>
<artifactId>my-maven-plugin-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>my-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<id>my-maven-plugin</id>
<goals>
<goal>validate</goal>
</goals>
<configuration>
<message>my-maven-plugin:validate</message>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>my-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
.../my-maven-plugin $ mvn clean install
...
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ my-maven-plugin ---
[INFO] Installing D:\_dev\eclipse.wksp.se\my-maven-plugin\target\my-maven-plugin-0.0.1-SNAPSHOT.jar to D:\.m2\igb\my-maven-plugin\0.0.1-SNAPSHOT\my-maven-plugin-0.0.1-SNAPSHOT.jar
[INFO] Installing D:\_dev\eclipse.wksp.se\my-maven-plugin\pom.xml to D:\.m2\igb\my-maven-plugin\0.0.1-SNAPSHOT\my-maven-plugin-0.0.1-SNAPSHOT.pom
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (test-after-install) @ my-maven-plugin ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running name.broser.gerold.maven.plugins.ValidateMojoTest
00:03:22.200 [main] DEBUG name.broser.gerold.maven.plugins.ValidateMojoTest -
Using POM '...\src\test\resources\my-maven-plugin-test\pom.xml'.
00:03:22.296 [main] DEBUG name.broser.gerold.maven.plugins.ValidateMojoTest -
Live testing my plugin's validate goal ...
################################################################################
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< igb:my-maven-plugin-test >----------------------
[INFO] Building my-maven-plugin-test 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- my-maven-plugin:0.0.1-SNAPSHOT:validate (my-maven-plugin) @ my-maven-plugin-test ---
[debug] message:
my-maven-plugin:validate.execute()...
[debug] project:
MavenProject: igb:my-maven-plugin-test:0.0.1-SNAPSHOT @ D:\_dev\eclipse.wksp.se\my-maven-plugin\src\test\resources\my-maven-plugin-test\pom.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.188 s
[INFO] Finished at: 2021-01-02T00:03:23+01:00
[INFO] ------------------------------------------------------------------------
################################################################################
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.074 s - in name.broser.gerold.maven.plugins.ValidateMojoTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.908 s
[INFO] Finished at: 2021-01-02T00:03:23+01:00
[INFO] ------------------------------------------------------------------------
正如开头提到的,这也可以用 Maven Invoker Plugin 来完成。但它的输出只是:
[INFO] --- maven-invoker-plugin:3.2.1:integration-test (test-after-install) @ my-maven-plugin ---
[INFO] Building: pom.xml
[INFO] pom.xml .......................................... SUCCESS (1.9 s)
没有构建步骤输出,没有日志输出,甚至在创建的 .../target/its/build.log
中也没有:
INFO] Scanning for projects...
[INFO]
[INFO] -----< name.broser.gerold.maven.plugins:my-maven-plugin-test >-----
[INFO] Building my-maven-plugin-test 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.082 s
[INFO] Finished at: 2021-01-05T14:01:06+01:00
[INFO] ------------------------------------------------------------------------