Cookbook:如何使用 Maven 插件测试工具?

本指南旨在为那些开发 Maven 插件的人提供参考,其中包含针对常见测试用例的自包含参考和解决方案。

先决条件

我们假设您已经创建了一个插件。在这本食谱中,我们引用了 Maven Archetype 插件生成的maven-my-plugin中的MyMojo,即:

mvn archetype:create \
  -DgroupId=org.apache.maven.plugin.my \
  -DartifactId=maven-my-plugin \
  -DarchetypeArtifactId=maven-archetype-mojo

生成的结构应该是:

maven-my-plugin
  |- pom.xml
  +- src/
   +- main/
      +- java/
        +- org/
          +- apache/
            +- maven/
              +- plugin/
                +- my/
                  |- MyMojo.java

食谱

添加maven-plugin-testing-harness依赖项

像往常一样,只需在 pom.xml 中添加maven-plugin-testing-harness如下所示。请务必指定测试范围。

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.plugin-testing</groupId>
      <artifactId>maven-plugin-testing-harness</artifactId>
      <scope>test</scope>
    </dependency>
    ...
  </dependencies>
  ...
</project>

创建一个MyMojoTest

在src/test/java/org/apache/maven/plugin/my目录中创建一个MyMojoTest(按照惯例)类。这个类应该从maven-plugin-testing-harness扩展AbstractMojoTestCase

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();

        ...
    }
}

在这种情况下,testSomething()将针对名为project-to-test的 Maven 项目测试MyMojo

注意:按照惯例,用于单元测试的项目应该在测试资源目录中。

作为扩展AbstractMojoTestCase的替代方法,并且在使用 Junit-4.10 ff. 时,您可以使用MojoRule,它只是嵌入了AbstractMojoTestCase

当您不需要每个测试方法中的功能时,您可以使用@WithoutMojo注释来跳过规则执行。

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()
    {
      ...
    }

}

配置项目到测试的pom

像往常一样创建一个pom。groupId 和 artifactId 的名称并不重要,因为不会部署此项目。

<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>

执行测试

像往常一样,只需调用:

mvn test