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.
Prerequisites
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
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.
<project> ... <dependencies> <dependency> <groupId>org.apache.maven.plugin-testing</groupId> <artifactId>maven-plugin-testing-harness</artifactId> <scope>test</scope> </dependency> ... </dependencies> ... </project>
Create a MyMojoTest
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
.
import org.apache.maven.plugin.testing.AbstractMojoTestCase; public class MyMojoTest extends AbstractMojoTestCase { /** {@inheritDoc} */ protected void setUp() throws Exception { // required super.setUp(); ... } /** {@inheritDoc} */ protected void tearDown() throws Exception { // required super.tearDown(); ... } /** * @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 ); 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 ); myMojo.execute(); ... } /** Do not need the MojoRule. */ @WithoutMojo @Test public void testSomethingWhichDoesNotNeedTheMojoAndProbablyShouldBeExtractedIntoANewClassOfItsOwn() { ... } }
Configuring project-to-test
pom
Just create a pom as usual. The names for groupId and artifactId don't really matter since this project will not be deployed.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.maven.plugin.my.unit</groupId> <artifactId>project-to-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Test MyMojo</name> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>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> </configuration> </plugin> </plugins> </build> </project>
Execute test
As usual, just call:
mvn test