diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java
index 7fc4fdf..7b0acf4 100644
--- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java
@@ -30,7 +30,7 @@
* which Mojo should be instantiated and how it should be configured.
*
*
The annotation requires a {@code goal} attribute to specify which Mojo goal
- * should be instantiated. Optionally, a custom {@code pom} file can be specified
+ * should be instantiated. Optionally, a custom {@code POM} file can be specified
* to provide specific configuration for the test.
*
* Example usage on a test method:
@@ -85,7 +85,24 @@
@Target({ElementType.METHOD, ElementType.PARAMETER})
public @interface InjectMojo {
+ /**
+ * Specifies the goal of the Mojo to instantiate.
+ * This is a required attribute that maps to the Mojo's {@code @Mojo(name = "...")}
+ * annotation value.
+ *
+ * @return the goal name of the Mojo to test
+ */
String goal();
+ /**
+ * Specifies an optional POM file to use for Mojo configuration.
+ * The path is relative to the test class location.
+ *
+ * NOTE: only plugin configuration is taken from provided POM, all other tags are ignored.
+ *
+ * If not specified, the default project configuration will be used.
+ *
+ * @return the path to a custom POM file, or an empty string to use defaults
+ */
String pom() default "";
}
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
index 800f2a7..36726cb 100644
--- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
@@ -138,7 +138,10 @@
*
**
* For custom POM configurations, you can specify a POM file using the {@link InjectMojo#pom()}
- * attribute. The extension will merge this configuration with default test project settings.
*
+ * attribute. The extension will merge this configuration with default test project settings.
+ *
+ * NOTE: only plugin configuration is taken from provided POM, all other tags are ignored.
+ *
*
* @see MojoTest
* @see InjectMojo
diff --git a/maven-plugin-testing-harness/src/site/markdown/examples/artifact.md b/maven-plugin-testing-harness/src/site/markdown/examples/artifact.md
index 3168907..77f3cc4 100644
--- a/maven-plugin-testing-harness/src/site/markdown/examples/artifact.md
+++ b/maven-plugin-testing-harness/src/site/markdown/examples/artifact.md
@@ -23,203 +23,103 @@ date: February 2008
### NOTE
-`JUnit 3` based tests are deprecated since `3.4.0`.
+**Note**: This example improves the [cookbook](../getting-started/index.html) to play with artifact handler.
-Use JUnit 5 annotations, consult [javadocs](../apidocs/org/apache/maven/api/plugin/testing/package-summary.html) for examples.
- **Note**: This example improves the [cookbook](../getting-started/index.html) to play with artifact handler.
+Sometimes, your Mojo uses project artifact and ArtifactHandler mechanisms. For instance, you could need to filter on Java projects, i.e.:
+```java
+import javax.inject.Inject;
- Sometimes, your Mojo uses project artifact and ArtifactHandler mechanisms. For instance, you could need to filter on Java projects, i.e.:
+import org.apache.maven.project.MavenProject;
-
-
-```
-public class MyMojo
- extends AbstractMojo
-{
+public class MyMojo extends AbstractMojo {
/**
* The Maven Project.
*/
- @Component
- protected MavenProject project;
-
- public void execute()
- throws MojoExecutionException
- {
- ...
-
- ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler();
- if ( "java".equals( artifactHandler.getLanguage() ) )
- {
- ...
- }
-
- ...
- }
-}
-```
-
-### Create Stubs
-
-
-
-```
-public class MyArtifactHandlerStub
- extends DefaultArtifactHandler
-{
- private String language;
-
- public String getLanguage()
- {
- if ( language == null )
- {
- language = "java";
- }
-
- return language;
- }
+ private final MavenProject project;
- public void setLanguage( String language )
- {
- this.language = language;
+ @Inject
+ MyMojo(MavenProject project) {
+ this.project = project;
}
-}
-```
-
-
-```
-public class MyArtifactStub
- extends ArtifactStub
-{
- private String groupId;
-
- private String artifactId;
-
- private String version;
-
- private String packaging;
- private VersionRange versionRange;
+ public void execute() throws MojoExecutionException {
+ // ...
- private ArtifactHandler handler;
-
- /**
- * @param groupId
- * @param artifactId
- * @param version
- * @param packaging
- */
- public ProjectInfoPluginArtifactStub( String groupId, String artifactId,
- String version, String packaging )
- {
- this.groupId = groupId;
- this.artifactId = artifactId;
- this.version = version;
- this.packaging = packaging;
- versionRange = VersionRange.createFromVersion( version );
- }
-
- /** {@inheritDoc} */
- public void setGroupId( String groupId )
- {
- this.groupId = groupId;
- }
-
- /** {@inheritDoc} */
- public String getGroupId()
- {
- return groupId;
- }
-
- /** {@inheritDoc} */
- public void setArtifactId( String artifactId )
- {
- this.artifactId = artifactId;
- }
-
- /** {@inheritDoc} */
- public String getArtifactId()
- {
- return artifactId;
- }
-
- /** {@inheritDoc} */
- public void setVersion( String version )
- {
- this.version = version;
- }
-
- /** {@inheritDoc} */
- public String getVersion()
- {
- return version;
- }
-
- /**
- * @param packaging
- */
- public void setPackaging( String packaging )
- {
- this.packaging = packaging;
- }
-
- /**
- * @return the packaging
- */
- public String getPackaging()
- {
- return packaging;
- }
-
- /** {@inheritDoc} */
- public VersionRange getVersionRange()
- {
- return versionRange;
- }
-
- /** {@inheritDoc} */
- public void setVersionRange( VersionRange versionRange )
- {
- this.versionRange = versionRange;
- }
-
- /** {@inheritDoc} */
- public ArtifactHandler getArtifactHandler()
- {
- return handler;
- }
+ ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler();
+ if ("java".equals(artifactHandler.getLanguage())) {
+ //...
+ }
- /** {@inheritDoc} */
- public void setArtifactHandler( ArtifactHandler handler )
- {
- this.handler = handler;
+ // ...
}
}
```
+### Create a test
+
+```java
+import org.apache.maven.api.di.Provides;import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.handler.ArtifactHandler;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;import org.apache.maven.project.MavenProject;
+import org.junit.jupiter.api.Nested;
+import org.mockito.Mockito;
+
+@MojoTest
+class ArtifactTest {
+
+ @Inject
+ private MavenProject project;
+
+ @Test
+ @InjectMojo(goal = "test")
+ void testUsingMockito(MyMojo mojo) {
+ // Mock ArtifactHandler
+ ArtifactHandler artifactHandler = Mockito.mock(ArtifactHandler.class);
+ Mockito.when(artifactHandler.getLanguage()).thenReturn("java");
+
+ // Mock Artifact
+ Artifact artifact = Mockito.mock(Artifact.class);
+ Mockito.when(artifact.getArtifactHandler()).thenReturn(artifactHandler);
+
+ // Set the mocked Artifact to the default provided project
+ project.setArtifact(artifact);
+
+ // Now you can test your Mojo logic that depends on the ArtifactHandler
+ mojo.execute();
+ }
+
+ @Nested
+ class NestedTest1 {
+
+ @Inject
+ private ArtifactHandlerManager artifactHandlerManager;
+
+ @Provides
+ MavenProject stubbedProject() {
+ MavenProject stubProject = new CustomMavenProject(); // your custom implementation
+
+ ArtifactHandler stubArtifactHandler = new CustomArtifactHandler(); // your custom implementation
+
+ // You can also get a real ArtifactHandler from the manager if needed
+ ArtifactHandler jarArtifactHandler = artifactHandlerManager.getArtifactHandler("jar");
+
+ Artifact stubArtifact = new CustomArtifact(stubArtifactHandler); // your custom implementation
+
+ stubProject.setArtifact(stubArtifact);
+ return stubProject;
+ }
-```
-public class MyProjectStub
- extends MavenProjectStub
-{
- /**
- * Default constructor
- */
- public MyProjectStub()
- {
- ...
-
- Artifact artifact = new MyArtifactStub( getGroupId(), getArtifactId(),
- getVersion(), getPackaging() );
- artifact.setArtifactHandler( new MyArtifactHandlerStub() );
- setArtifact( artifact );
-
- ...
+ @Test
+ @InjectMojo(goal = "test")
+ void testUsingStubbedProject (MyMojo mojo) {
+ // Use the stubbed project in your test
+ mojo.execute();
+ }
}
-
- ...
}
```
-
diff --git a/maven-plugin-testing-harness/src/site/markdown/examples/complex-mojo-parameters.md b/maven-plugin-testing-harness/src/site/markdown/examples/complex-mojo-parameters.md
index fd76055..f979534 100644
--- a/maven-plugin-testing-harness/src/site/markdown/examples/complex-mojo-parameters.md
+++ b/maven-plugin-testing-harness/src/site/markdown/examples/complex-mojo-parameters.md
@@ -20,172 +20,141 @@ date: February 2008
## Testing Complex Mojo Parameters
-### NOTE
+**Note**: This example improves the [cookbook](../getting-started/index.html) for testing complex Mojo parameters.
-`JUnit 3` based tests are deprecated since `3.4.0`.
+In real plugin development, you will use specific Maven objects like `MavenProject`, `MavenSession`, `MavenSettings` and so on.
-Use JUnit 5 annotations, consult [javadocs](../apidocs/org/apache/maven/api/plugin/testing/package-summary.html) for examples.
+### Provided mocks and stubs
- **Note**: This example improves the [cookbook](../getting-started/index.html) for testing complex Mojo parameters.
+The Maven Plugin Testing Harness provides mocks and stubs for the following Maven objects.
+For creating mocks [Mockito](https://site.mockito.org/) framework is used.
+#### MavenSession
- In real plugin development, you will use specific Maven objects like `MavenProject`, `ArtifactRepository` or `MavenSettings`. You could use them by defining stubs.
+There is provided a **mock** for `MavenSession` with basic configuration:
+- `session#getUserProperties` and `session#getSystemProperties` empty `Properties` objects.
+- `session#getCurrentProject` - a current prepared `MavenProject`
+- `session#getLocalRepository` - equals to `request#getLocalRepository`
+- `session#getRequest` returns a `spy` for `DefaultMavenExecutionRequest` with configuration
+ - `request#getStartTime` - celling time
+ - `request#getBaseDirectory()` - current base directory
+ - `request#getUserProperties`, `request#getSystemProperties` - copy of `MavenSession` properties
+ - `request#getLocalRepository`, `request#getLocalRepositoryPath` - point to local repository in `${basedir}/target/local-repo`
+ - `request#getRemoteRepositories`, `request#getPluginArtifactRepositories` - default remote repositories for Maven Central
- Suppose that you have the following dependencies in the maven-my-plugin pom:
+If `@MojoTest(realRepositorySession = true)` is used, then `session#getRepositorySession` returns
+a real `RepositorySystemSession` configured with local repository in `${basedir}/target/local-repo`
+and default remote repositories for Maven Central.
+#### MavenProject
+There is provided a **spy** for `MavenProject` with basic configuration:
-```
-
- ...
-
-
- org.apache.maven
- maven-artifact
- 2.0.8
-
-
- org.apache.maven
- maven-project
- 2.0.8
-
- ...
-
-
-```
+- `project#getBasedir` - current base directory
+- `project#getCompileSourceRoots` - `${basedir}/src/main/java`
+- `project#getTestCompileSourceRoots` - `${basedir}/src/test/java`
+- `project#getBuild` - a spy for `Build` with configuration
+ - `build#getDirectory` - `${basedir}/target`
+ - `build#getOutputDirectory` - `${basedir}/target/classes`
+ - `build#getTestOutputDirectory` - `${basedir}/target/test-classes`
+ - `build#getSourceDirectory` - `${basedir}/src/main/java`
+ - `build#getTestSourceDirectory` - `${basedir}/src/test/java`
+ - `build#getResources` - `${basedir}/src/main/resources`
+ - `build#getTestResources` - `${basedir}/src/test/resources`
- You will add the following in the `MyMojo`:
+If `@MojoTest(realRepositorySession = true)` is used, then `project#getRemote*Repositories` returns default remote repositories for Maven Central.
+#### MojoExecution
+There is provided a **spy** for `MojoExecution` with current plugin Mojo descriptor.
-```
-public class MyMojo
- extends AbstractMojo
-{
- /**
- * The Maven Project.
- */
- @Parameter( defaultValue = "${project}", readonly = true )
- protected MavenProject project;
-
- /**
- * Local Repository.
- */
- @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
- protected ArtifactRepository localRepository;
-
- /**
- * The Maven Settings.
- */
- @Parameter( defaultValue = "${settings}", readonly = true )
- private Settings settings;
-
- ...
-}
-```
+#### Plugin logger
-### Create Stubs
+There is provided a **spy** for Slf4j wrapper of `org.apache.maven.plugin.logging.Log` interface.
+You can verify log messages using Mockito verifications.
+### Create custom Stubs for Maven objects
- You need to create stub objects to run `MyMojoTest#testSomething()`. By convention, the package name should reflect the stubs, i.e. in our case `org.apache.maven.plugin.my.stubs`.
+You can create your own stubs for Maven objects by define them in plugin test.
+If you provide your own stub for a Maven object, then it will be used instead of the default provided one.
+```java
+import javax.inject.Inject;
-```
-public class MyProjectStub
- extends MavenProjectStub
-{
- /**
- * Default constructor
- */
- public MyProjectStub()
- {
- MavenXpp3Reader pomReader = new MavenXpp3Reader();
- Model model;
- try
- {
- model = pomReader.read( ReaderFactory.newXmlReader( new File( getBasedir(), "pom.xml" ) ) );
- setModel( model );
- }
- catch ( Exception e )
- {
- throw new RuntimeException( e );
- }
+import org.apache.maven.api.di.Provides;
+import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.settings.Settings;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+@MojoTest
+class MyMojoTest {
- setGroupId( model.getGroupId() );
- setArtifactId( model.getArtifactId() );
- setVersion( model.getVersion() );
- setName( model.getName() );
- setUrl( model.getUrl() );
- setPackaging( model.getPackaging() );
-
- Build build = new Build();
- build.setFinalName( model.getArtifactId() );
- build.setDirectory( getBasedir() + "/target" );
- build.setSourceDirectory( getBasedir() + "/src/main/java" );
- build.setOutputDirectory( getBasedir() + "/target/classes" );
- build.setTestSourceDirectory( getBasedir() + "/src/test/java" );
- build.setTestOutputDirectory( getBasedir() + "/target/test-classes" );
- setBuild( build );
-
- List compileSourceRoots = new ArrayList();
- compileSourceRoots.add( getBasedir() + "/src/main/java" );
- setCompileSourceRoots( compileSourceRoots );
-
- List testCompileSourceRoots = new ArrayList();
- testCompileSourceRoots.add( getBasedir() + "/src/test/java" );
- setTestCompileSourceRoots( testCompileSourceRoots );
+ // define your stub for MavenProject
+ @Provides
+ MavenProject stubProject() {
+ // return your stub implementation
+ return new MavenProjectStub();
}
- /** {@inheritDoc} */
- public File getBasedir()
- {
- return new File( super.getBasedir() + "/src/test/resources/unit/project-to-test/" );
+ @Provides
+ MavenSession stubSession() {
+ // return your stub implementation
+ return new MyMavenSessionStub();
}
-}
-```
+ // inject the stubbed or default MavenSession
+ @Inject
+ private MavenSession session;
-```
-public class SettingsStub
- extends Settings
-{
- /** {@inheritDoc} */
- public List getProxies()
- {
- return Collections.EMPTY_LIST;
+ @Inject
+ private Log log;
+
+ @BeforeEach
+
+ void setup() {
+ // customize injected stubs or mocks
+ Mockito.when(session.getSettings()).thenReturn(new MySettingsStub());
}
-}
-```
+ @Test
+ @InjectMojo(goal = "my-goal")
+ void myMojoTest(MyMojo mojo) {
+ mojo.execute();
+ // your verifications, eg
+ Mockito.verify(log).info("My info log message");
+ }
-### Configure `project-to-test` pom
+ // you can also group stubs in nested test classes
+ @Nested
+ class NestedTest {
+ // define your stub for MavenProject in nested class
+ @Provides
+ MavenProject stubProject() {
+ // return your stub implementation
+ return new MavenProjectStub2();
+ }
+ @BeforeEach
+ void setup() {
+ // customize injected stubs or mocks for this nested class
+ Mockito.when(session.getSettings()).thenReturn(new MySettingsStub());
+ }
+ @Test
+ @InjectMojo(goal = "my-goal")
+ void myMojoTest(MyMojo mojo) {
+ mojo.execute();
+ // your verifications
+ }
+ }
+}
```
-
- ...
-
-
-
- maven-my-plugin
-
-
- target/test-harness/project-to-test
-
-
- ${localRepository}
-
-
-
-
-
-
-
-
-```
-
-
diff --git a/maven-plugin-testing-harness/src/site/markdown/examples/multiproject.md b/maven-plugin-testing-harness/src/site/markdown/examples/multiproject.md
index 7b76260..be42c91 100644
--- a/maven-plugin-testing-harness/src/site/markdown/examples/multiproject.md
+++ b/maven-plugin-testing-harness/src/site/markdown/examples/multiproject.md
@@ -22,134 +22,60 @@ date: February 2008
### NOTE
-`JUnit 3` based tests are deprecated since `3.4.0`.
-
-Use JUnit 5 annotations, consult [javadocs](../apidocs/org/apache/maven/api/plugin/testing/package-summary.html) for examples.
-
**Note**: This example improves the [cookbook](../getting-started/index.html) for multi-project testing.
+Your Mojo should have `aggregator` parameter set to `true` - [Maven Plugin Tools Java Annotations](https://maven.apache.org/plugin-tools/maven-plugin-tools-annotations/index.html)
- Your Mojo should have `@aggregator` parameter, i.e.:
-
-
-
- - with java annotations ([maven-plugin-plugin 3.x](/plugin-tools/)):
-
-```
-@Mojo( name = "touch", aggregator = true )
-public class MyMojo
- extends AbstractMojo
-{
+```java
+@Mojo(name = "touch", aggregator = true)
+public class MyMojo extends AbstractMojo {
...
}
```
- - or with javadoc tags:
-
-```
-/**
- * @goal touch
- * @aggregator
- */
-public class MyMojo
- extends AbstractMojo
-{
- ...
-}
-```
-
+To test a Mojo in a multiproject area, you need to define several stubs, i.e. for the main test project and its modules.
- To test a Mojo in a multiproject area, you need to define several stubs, i.e. for the main test project and its modules.
+### Configure Mian project and create Stubs for the sub projects
+```java
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+import org.mockito.Mockito;
-### Create Stubs
+@MojoTest
+class AggregateTest {
+ @Inject
+ private MavenProject project;
- Stub for the main test project:
+ @Inject
+ private MavenSession session;
+ @BeforeEach
+ void setup() {
+ // Configure the main project as execution root
+ project.setExecutionRoot(true);
+ MavenProject stub1 = new MavenProject();
+ // configure stub1 as needed
-```
-public class MyProjectStub
- extends MavenProjectStub
-{
- /**
- * Default constructor
- */
- public MyProjectStub()
- {
- ...
-
- setExecutionRoot( true );
- }
+ MavenProject stub2 = new MavenProject();
+ // configure stub2 as needed
- /** {@inheritDoc} */
- public MavenProject getExecutionProject()
- {
- return this;
+ // return all projects in the reactor - reactorProjects
+ Mockito.when(session.getProjects()).thenReturn(Arrays.asList(project, stub1, stub2));
}
-}
-```
-
- Stubs for the subprojects:
+ @Test
+ @Basedir("/unit/aggregate-test")
+ @InjectMojo(goal = "aggregate")
+ void aggregate(AggregatorMojo mojo) throws Exception {
+ mojo.execute();
-```
-public class SubProject1Stub
- extends MavenProjectStub
-{
- /**
- * Default constructor
- */
- public SubProject1Stub()
- {
- ...
+ // Verify behavior across all projects
}
}
```
-
-
-```
-public class SubProject2Stub
- extends MavenProjectStub
-{
- /**
- * Default constructor
- */
- public SubProject2Stub()
- {
- ...
- }
-}
-```
-
-
-### Configure `project-to-test` pom
-
-
-
-```
-
- ...
-
-
-
- maven-my-plugin
-
- ...
-
-
-
-
-
-
-
-
-
-
-```
-
-
diff --git a/maven-plugin-testing-harness/src/site/markdown/getting-started/index.md b/maven-plugin-testing-harness/src/site/markdown/getting-started/index.md
index 2b943db..83506b5 100644
--- a/maven-plugin-testing-harness/src/site/markdown/getting-started/index.md
+++ b/maven-plugin-testing-harness/src/site/markdown/getting-started/index.md
@@ -20,105 +20,19 @@ date: 2008-08-27
## Cookbook: How To Use Maven Plugin Testing Harness?
-
- This guide is intended as a reference for those developing Maven plugins, with self-contained references and solutions for common testing cases.
-
-### NOTE
-
-`AbstractMojoTestCase` is based on `JUnit 3` and is deprecated since `3.4.0`.
-
-Instead of it use `@MojoTest` and other JUnit 5 annotations, consult [javadocs](../apidocs/org/apache/maven/api/plugin/testing/package-summary.html) for examples.
-
-#### Migration receipts
-
-Replace
-
-```java
-public class MyMojoTest extends AbstractMojoTestCase {
-}
-```
-
-by
-
-```java
-@MojoTest
-class MyMojoTest {
-}
-```
-
----
-
- Replace
-
-```java
-MyMojo myMojo = (MyMojo) lookupMojo("goal", pom);
-```
-
-by
-
-```java
-@InjectMojo(goal = "goal", pom = "src/test/resources/unit/project-to-test/pom.xml")
-```
-
----
-
-Replace
-
-```java
-public void test() {}
- MyCoponent myCoponent = lookup(MyCoponent.class);
-}
-```
-
-by
-
-```java
-@MojoTest
-class MyMojoTest {
-
- @Inject
- private MyCoponent myCoponent;
-}
-```
+This guide is intended as a reference for those developing Maven plugins, with self-contained references and solutions for common testing cases.
### Prerequisites
+We assume that you have already created a plugin. In this cookbook, we make reference to `MyMojo` in `maven-my-plugin`.
- We assume that you have already created a plugin. In this cookbook, we make reference to `MyMojo` in `maven-my-plugin` which is generated by the Maven Archetype Plugin, i.e.:
-
-
-```
-mvn archetype:create \
- -DgroupId=org.apache.maven.plugin.my \
- -DartifactId=maven-my-plugin \
- -DarchetypeArtifactId=maven-archetype-mojo
-```
-
- The generated structure should be:
-
-```
-maven-my-plugin
- |- pom.xml
- +- src/
- +- main/
- +- java/
- +- org/
- +- apache/
- +- maven/
- +- plugin/
- +- my/
- |- MyMojo.java
-```
-
-
-### Recipe
+You cane reference the [Guide to Developing Java Plugins](http://maven.apache.org/guides/plugin/guide-java-plugin-development.html) to create your first plugin.
+### Testing Maven Plugin
#### Add `maven-plugin-testing-harness` dependency
-
- As usual, just add `maven-plugin-testing-harness` as following in your pom. Be sure to specify `test` scope.
-
+As usual, just add `maven-plugin-testing-harness` as following in your POM. Be sure to specify `test` scope.
```
@@ -129,144 +43,85 @@ maven-my-plugin
maven-plugin-testing-harness
test
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
...
...
```
-
#### Create a `MyMojoTest`
+Create a `MyMojoTest` (by convention) class in `src/test/java/org/example/maven/plugin/my` directory.
- Create a `MyMojoTest` (by convention) class in `src/test/java/org/apache/maven/plugin/my` directory. This class should extend `AbstractMojoTestCase` from `maven-plugin-testing-harness`.
+```java
+import javax.inject.Inject;
-```
-import org.apache.maven.plugin.testing.AbstractMojoTestCase;
-
-public class MyMojoTest
- extends AbstractMojoTestCase
-{
- /** {@inheritDoc} */
- protected void setUp()
- throws Exception
- {
- // required
- super.setUp();
+import org.apache.maven.api.plugin.testing.Basedir;
+import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.api.plugin.testing.MojoParameter;
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.execution.MavenSession;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
- ...
- }
+@MojoTest
+class MyMojoTest {
- /** {@inheritDoc} */
- protected void tearDown()
- throws Exception
- {
- // required
- super.tearDown();
+ @Inject
+ private MavenSession session;
- ...
+ // optional setup before each test
+ @BeforeEach
+ void setUp() {
+ // properties added to the Maven session can by used in the plugin configuration
+ session.getUserProperties().setProperty("someProperty", "someValue");
}
- /**
- * @throws Exception if any
- */
- public void testSomething()
- throws Exception
- {
- File pom = getTestFile( "src/test/resources/unit/project-to-test/pom.xml" );
- assertNotNull( pom );
- assertTrue( pom.exists() );
-
- MyMojo myMojo = (MyMojo) lookupMojo( "touch", pom );
- assertNotNull( myMojo );
+ @Test
+ @InjectMojo(goal = "touch", pom = "src/test/resources/unit/project-to-test/pom.xml")
+ public void testSomething(MyMojo myMojo) throws Exception {
myMojo.execute();
-
...
}
-}
-```
-
- In this case, `testSomething()` will test `MyMojo` against a Maven project called `project-to-test`.
-
-
- **Note**: By convention, projects for unit testing your should be in the test resources directory.
-
-
- Alternatively to extending `AbstractMojoTestCase` and when using Junit-4.10 ff., you may use a `MojoRule`, which just embeds an `AbstractMojoTestCase`.
-
-
- When you do not need the functionality in every test method, you may use the `@WithoutMojo` annotation to skip rule executions.
-
-
-```
-
-import org.apache.maven.plugin.testing.MojoRule;
-import org.apache.maven.plugin.testing.WithoutMojo;
-
-import org.junit.Rule;
-import static org.junit.Assert.*;
-import org.junit.Test;
-
-public class MyMojoTest
-{
- @Rule
- public MojoRule rule = new MojoRule()
- {
- @Override
- protected void before() throws Throwable
- {
- }
-
- @Override
- protected void after()
- {
- }
- };
-
- /**
- * @throws Exception if any
- */
@Test
- public void testSomething()
- throws Exception
- {
- File pom = rule.getTestFile( "src/test/resources/unit/project-to-test/pom.xml" );
- assertNotNull( pom );
- assertTrue( pom.exists() );
-
- MyMojo myMojo = (MyMojo) rule.lookupMojo( "touch", pom );
- assertNotNull( myMojo );
+ // you can use @Basedir pointing to test classpath resource
+ @Basedir("/unit/project-to-test")
+ // if you not provide 'pom' parameter, it will look for 'pom.xml' in basedir
+ @InjectMojo(goal = "touch", pom = "another-pom.xml")
+ public void testSomething2(MyMojo myMojo) throws Exception {
myMojo.execute();
-
...
}
- /** Do not need the MojoRule. */
- @WithoutMojo
@Test
- public void testSomethingWhichDoesNotNeedTheMojoAndProbablyShouldBeExtractedIntoANewClassOfItsOwn()
- {
- ...
+ @InjectMojo(goal = "touch")
+ // you can provide simple parameters directly in the test method, without using a POM file
+ @MojoParameter(name = "parameter1Name", value = "parameter1Value")
+ @MojoParameter(name = "parameter2Name", value = "parameter2Value")
+ public void testSomething3(MyMojo myMojo) throws Exception {
+ myMojo.execute();
+ ...
}
-
}
-
-
```
-#### Configuring `project-to-test` pom
-
+**Note**: By convention, projects for unit testing your should be in the test resources directory.
- Just create a pom as usual. The names for groupId and artifactId don't really matter since this project will not be deployed.
+#### Configuring `project-to-test` POM
+ Just create a POM as usual. Only plugin configuration is processed by the testing harness. **All other parts of the POM are ignored.**
-
-```
+```xml
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.apache.maven.plugin.my.unit
@@ -275,22 +130,18 @@ public class MyMojoTest
jar
Test MyMojo
-
-
- junit
- junit
- 3.8.1
- test
-
-
-
maven-my-plugin
- target/test-harness/project-to-test
+ ${basedir}/target/test-output
+
+ value1
+
+ ${someProperty}
+
@@ -301,23 +152,17 @@ public class MyMojoTest
#### Execute test
-
- As usual, just call:
-
+As usual, just call:
```
mvn test
```
-
-
### Resources
-
-
- 1 [Guide to Developing Java Plugins](http://maven.apache.org/guides/plugin/guide-java-plugin-development.html)
-
- 1 [Guide to Configuring Plugins](http://maven.apache.org/guides/mini/guide-configuring-plugins.html)
+- [Guide to Developing Java Plugins](http://maven.apache.org/guides/plugin/guide-java-plugin-development.html)
+- [Guide to Configuring Plugins](http://maven.apache.org/guides/mini/guide-configuring-plugins.html)
+- [Project unit tests](https://github.com/apache/maven-plugin-testing/tree/maven-plugin-testing-3.x/maven-plugin-testing-harness/src/test)
diff --git a/maven-plugin-testing-harness/src/site/markdown/index.md b/maven-plugin-testing-harness/src/site/markdown/index.md
index 9de97c5..77af42b 100644
--- a/maven-plugin-testing-harness/src/site/markdown/index.md
+++ b/maven-plugin-testing-harness/src/site/markdown/index.md
@@ -20,8 +20,10 @@ date: February 2008
## Maven Plugin Testing Harness
+The Maven Plugin Testing Harness provides mechanisms to manage tests on Mojos, i.e. by pre-constructing the [Plexus](https://codehaus-plexus.github.io/plexus-containers/)/[Sisu](https://eclipse.dev/sisu/org.eclipse.sisu.plexus/) components,
+providing stub objects for Maven functionality such as projects, and populating fields from an XML file that resembles the plugin configuration in the POM.
-The Maven Plugin Testing Harness provides mechanisms to manage tests on Mojos, i.e. by pre-constructing the [Plexus](http://plexus.codehaus.org) components, providing stub objects for Maven functionality such as projects, and populating fields from an XML file that resembles the plugin configuration in the POM.
+The Maven Plugin Testing Harness provides default stubs/mocks for most commonly used Maven objects, such as `MavenProject`, `MavenSession`, etc.
The best way to start is to read the cookbook [How to use Maven Plugin Testing Harness](./getting-started/index.html).
@@ -31,12 +33,14 @@ Since version `3.4.0`, the Maven Plugin Testing Harness has been migrated to use
This change allows for more modern testing practices and improved integration with other tools.
JUnit 5 extension `MojoExtension` and annotation `@MojoTest` have similar functionalities
-as in [Maven 4](https://maven.apache.org/ref/4-LATEST/maven-impl-modules/maven-testing/apidocs/index.html)
+as in [Maven 4](https://maven.apache.org/ref/4-LATEST/impl/maven-testing/apidocs/index.html)
for easier migration of tests for Maven 4.
Project still supports JUnit 3/4 `AbstractMojoTestCase` and JUnit 4 `MojoRule` tests for backward compatibility
but new tests should be written using JUnit 5.
+There are some [migration receipts](./migration-3.4.0.html) to help you migrate your existing tests.
+
Therefore, some project dependencies have been set as optional to avoid conflicts with existing JUnit 3/4 and JUnit 5 tests.
Your project should depend on the following artifacts, if needed:
@@ -48,17 +52,12 @@ Your project should depend on the following artifacts, if needed:
### Examples
- The following examples shows how to use the Testing Harness in more advanced use cases:
-
+The following examples shows how to use the Testing Harness in more advanced use cases:
- [Testing Complex Mojo Parameters](./examples/complex-mojo-parameters.html)
-
- [Testing Multiproject](./examples/multiproject.html)
-
- [Testing Using Repositories](./examples/repositories.html)
-
- [Testing Project Artifact](./examples/artifact.html)
-
- [Plugins testing summary](https://maven.apache.org/plugin-developers/plugin-testing.html)
diff --git a/maven-plugin-testing-harness/src/site/markdown/migration-3.4.0.md b/maven-plugin-testing-harness/src/site/markdown/migration-3.4.0.md
new file mode 100644
index 0000000..50d611d
--- /dev/null
+++ b/maven-plugin-testing-harness/src/site/markdown/migration-3.4.0.md
@@ -0,0 +1,147 @@
+title: Migration to 3.4.0+
+author: Sławomir Jaranowski
+date: January 2026
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Migration to 3.4.0+
+
+Since version `3.4.0`, the Maven Plugin Testing Harness has been migrated to use JUnit 5 as the testing framework.
+This change allows for more modern testing practices and improved integration with other tools.
+
+### Migration receipts
+
+Replace
+
+```java
+public class MyMojoTest extends AbstractMojoTestCase {
+}
+```
+
+by
+
+```java
+@MojoTest
+class MyMojoTest {
+}
+```
+
+---
+
+Replace
+
+```java
+MyMojo myMojo = (MyMojo) lookupMojo("goal", pom);
+```
+
+by
+
+```java
+@InjectMojo(goal = "goal", pom = "src/test/resources/unit/project-to-test/pom.xml")
+```
+
+---
+
+Replace
+
+```java
+public void test() {}
+ MyCoponent myCoponent = lookup(MyCoponent.class);
+}
+```
+
+by
+
+```java
+@MojoTest
+class MyMojoTest {
+
+ @Inject
+ private MyCoponent myCoponent;
+}
+```
+
+Replace implementation of stubs in the configuration XML file from
+
+```xml
+
+ 4.0.0
+ exmaple.test
+ example
+ 1.0-SNAPSHOT
+
+
+
+ org.exmaple.plugins
+ my-maven-plugin
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+by code in the test class:
+
+```java
+import javax.inject.Inject;
+
+import java.util.Arrays;
+
+import org.apache.maven.api.di.Provides;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.settings.Settings;
+import org.junit.jupiter.api.BeforeEach;
+import org.mockito.Mockito;
+
+@MojoTest
+class MyMojoTest {
+
+ @Provides
+ MavenProject stubProject() {
+ // return your stub implementation
+ return new MavenProjectStub();
+ }
+
+ // default Mockito mock for MavenSession will be injected
+ @Inject
+ private MavenSession session;
+
+ // project crated by stubProject() method will be injected
+ @Inject
+ private MavenProject project;
+
+ @BeforeEach
+ void setup() {
+ MavenProject stub1 = new SubProject1Stub();
+ MavenProject stub2 = new SubProject2Stub();
+
+ // reactorProjects
+ Mockito.when(session.getProjects()).thenReturn(Arrays.asList(project, stub1, stub2));
+
+ Mockito.when(session.getSettings()).thenReturn(new Settings());
+ }
+}
+```
\ No newline at end of file
diff --git a/maven-plugin-testing-harness/src/site/site.xml b/maven-plugin-testing-harness/src/site/site.xml
index 8c6dc15..7c450bb 100644
--- a/maven-plugin-testing-harness/src/site/site.xml
+++ b/maven-plugin-testing-harness/src/site/site.xml
@@ -25,6 +25,7 @@ under the License.