This is an automated email from the ASF dual-hosted git repository.
sjaranowski pushed a commit to branch maven-plugin-testing-3.x
in repository https://gitbox.apache.org/repos/asf/maven-plugin-testing.git
The following commit(s) were added to refs/heads/maven-plugin-testing-3.x by
this push:
new d58f775 Rewrite documentation and examples with new MojoTest usage
d58f775 is described below
commit d58f77506a869f3ea7ee198e6bf0f1b27f05f33f
Author: Slawomir Jaranowski <[email protected]>
AuthorDate: Mon Jan 5 22:31:29 2026 +0100
Rewrite documentation and examples with new MojoTest usage
As AbstractMojoTestCase is deprecated we can point documentation to new
MojoTest and JUnit 5
---
.../maven/api/plugin/testing/InjectMojo.java | 19 +-
.../maven/api/plugin/testing/MojoExtension.java | 5 +-
.../src/site/markdown/examples/artifact.md | 256 ++++++-------------
.../markdown/examples/complex-mojo-parameters.md | 241 ++++++++----------
.../src/site/markdown/examples/multiproject.md | 138 +++--------
.../src/site/markdown/getting-started/index.md | 273 +++++----------------
.../src/site/markdown/index.md | 15 +-
.../src/site/markdown/migration-3.4.0.md | 147 +++++++++++
maven-plugin-testing-harness/src/site/site.xml | 1 +
.../plugin/testing/SimpleResolveMojoTest.java | 9 +
10 files changed, 460 insertions(+), 644 deletions(-)
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 @@ import java.lang.annotation.Target;
* which Mojo should be instantiated and how it should be configured.
*
* <p>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.</p>
*
* <p>Example usage on a test method:</p>
@@ -85,7 +85,24 @@ import java.lang.annotation.Target;
@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.
+ *
+ * <p><b>NOTE:</b> only plugin configuration is taken from provided POM,
all other tags are ignored.</p>
+ *
+ * <p>If not specified, the default project configuration will be used.</p>
+ *
+ * @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 @@ import static org.mockito.Mockito.spy;
* </pre>
**
* <p>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.</p>*
+ * attribute. The extension will merge this configuration with default test
project settings.</p>
+ *
+ * <p><b>NOTE:</b> only plugin configuration is taken from provided POM, all
other tags are ignored.</p>
+ *
*
* @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
<!-- under the License. -->
## 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:
-```
-<project>
- ...
- <dependencies>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-artifact</artifactId>
- <version>2.0.8</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-project</artifactId>
- <version>2.0.8</version>
- </dependency>
- ...
- </dependencies>
-</project>
-```
+- `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
+ }
+ }
+}
```
-<project>
- ...
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-my-plugin</artifactId>
- <configuration>
- <!-- Specify where this pom will output files -->
-
<outputDirectory>target/test-harness/project-to-test</outputDirectory>
-
- <!-- By default <<<${basedir}/target/local-repo", where basedir
refers
- to the basedir of maven-my-plugin. -->
- <localRepository>${localRepository}</localRepository>
- <!-- The defined stubs -->
- <project
implementation="org.apache.maven.plugin.my.stubs.MyProjectStub"/>
- <settings
implementation="org.apache.maven.plugin.my.stubs.SettingsStub"/>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
-```
-
-
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
-
-
-
-```
-<project>
- ...
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-my-plugin</artifactId>
- <configuration>
- ...
- <project
implementation="org.apache.maven.plugin.my.stubs.MyProjectStub"/>
- <reactorProjects>
- <project
implementation="org.apache.maven.plugin.my.stubs.SubProject1Stub"/>
- <project
implementation="org.apache.maven.plugin.my.stubs.SubProject2Stub"/>
- </reactorProjects>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
-```
-
-
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
<!-- under the License. -->
## 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.
```
<project>
@@ -129,144 +43,85 @@ maven-my-plugin
<artifactId>maven-plugin-testing-harness</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <scope>test</scope>
+ </dependency>
...
</dependencies>
...
</project>
```
-
#### 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
<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">
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.plugin.my.unit</groupId>
@@ -275,22 +130,18 @@ public class MyMojoTest
<packaging>jar</packaging>
<name>Test MyMojo</name>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
<build>
<plugins>
<plugin>
<artifactId>maven-my-plugin</artifactId>
<configuration>
<!-- Specify the MyMojo parameter -->
-
<outputDirectory>target/test-harness/project-to-test</outputDirectory>
+ <outputDirectory>${basedir}/target/test-output</outputDirectory>
+ <complexParameter>
+ <param1>value1</param1>
+ <!-- property set in BeforeEach method -->
+ <param2>${someProperty}</param2>
+ </complexParameter>
</configuration>
</plugin>
</plugins>
@@ -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
<!-- under the License. -->
## 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
+
+<!-- Licensed to the Apache Software Foundation (ASF) under one -->
+<!-- or more contributor license agreements. See the NOTICE file -->
+<!-- distributed with this work for additional information -->
+<!-- regarding copyright ownership. The ASF licenses this file -->
+<!-- to you under the Apache License, Version 2.0 (the -->
+<!-- "License"); you may not use this file except in compliance -->
+<!-- with the License. You may obtain a copy of the License at -->
+<!-- -->
+<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
+<!-- -->
+<!-- Unless required by applicable law or agreed to in writing, -->
+<!-- software distributed under the License is distributed on an -->
+<!-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -->
+<!-- KIND, either express or implied. See the License for the -->
+<!-- specific language governing permissions and limitations -->
+<!-- under the License. -->
+## 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
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>exmaple.test</groupId>
+ <artifactId>example</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.exmaple.plugins</groupId>
+ <artifactId>my-maven-plugin</artifactId>
+ <configuration>
+ <project implementation="org.example.plugin.stubs.MavenProjectStub"
/>
+ <settings implementation="org.apache.maven.settings.Settings" />
+ <reactorProjects>
+ <project
implementation="org.example.plugin.stubs.SubProject1Stub"/>
+ <project
implementation="org.example.plugin.stubs.SubProject2Stub"/>
+ </reactorProjects>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+```
+
+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.
<menu name="Overview">
<item name="Introduction" href="index.html"/>
<item name="Getting Started" href="/getting-started/index.html"/>
+ <item name="Migration to 3.4.0+" href="/migration-3.4.0.html"/>
<item name="JavaDocs" href="apidocs/index.html"/>
<item name="Source Xref" href="xref/index.html"/>
<item name="FAQ" href="/faq.html"/>
diff --git
a/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/SimpleResolveMojoTest.java
b/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/SimpleResolveMojoTest.java
index d5e9304..170af65 100644
---
a/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/SimpleResolveMojoTest.java
+++
b/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/SimpleResolveMojoTest.java
@@ -27,10 +27,12 @@ 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.apache.maven.plugin.logging.Log;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
@@ -47,6 +49,9 @@ class SimpleResolveMojoTest {
@Inject
private MavenSession session;
+ @Inject
+ private Log log;
+
@BeforeEach
void beforeEach() {
// optionally customize the session to use a temporary local repository
@@ -64,6 +69,8 @@ class SimpleResolveMojoTest {
@MojoParameter(name = "artifact", value =
"org.apache.commons:commons-lang3:3.20.0")
void artifactShouldBeResolved(SimpleResolveMojo mojo) {
assertDoesNotThrow(mojo::execute);
+
+ Mockito.verify(log, Mockito.times(1)).info(Mockito.contains("Resolved
artifact to"));
}
@Nested
@@ -73,6 +80,8 @@ class SimpleResolveMojoTest {
@MojoParameter(name = "artifact", value =
"org.apache.commons:commons-lang3:3.20.0")
void artifactShouldBeResolved(SimpleResolveMojo mojo) {
assertDoesNotThrow(mojo::execute);
+
+ Mockito.verify(log,
Mockito.times(1)).info(Mockito.contains("Resolved artifact to"));
}
}
}