在 GitHub 上叉我

使用 JUnit

配置 JUnit

要开始使用 JUnit,您需要将所需版本的 JUnit 添加到您的项目中:

<dependencies>
  [...]
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  [...]
</dependencies>

这是开始所需的唯一步骤 - 您现在可以在测试源目录中创建测试(例如,src/test/java)。

不同代的 JUnit 支持

Surefire 支持三代不同的 JUnit:JUnit 3.8.x、JUnit 4.x(串行提供程序)和 JUnit 4.7(具有并行支持的 junit-core 提供程序)。根据项目中的 JUnit 版本和配置参数(用于并行)选择提供程序。

JUnit 4.x 的升级检查

从 Surefire 2.7 版开始,选择运行哪些测试的算法发生了变化。从 2.7 开始,所有版本的 JUnit 只运行有效的 JUnit 测试,旧版本的插件也会运行满足命名约定的无效测试。

从 2.7 之前的 Surefire 版本升级时,可以使用 flag 运行构建-Dsurefire.junit4.upgradecheck。这将执行检查并通知您不会使用此版本的 Surefire 运行的任何无效测试(并且构建失败)。这仅在升级时用作工具,以检查是否将运行所有预期的测试。这是一个过渡功能,将在未来版本的 Surefire 中删除。

提供者选择

如果未配置任何内容,Surefire 会通过以下算法检测要使用的 JUnit 版本:

if the JUnit 5 Platform Engine is present in the project
    use junit-platform
if the JUnit version in the project >= 4.7 and the <<<parallel>>> configuration parameter has ANY value
    use junit47 provider
if JUnit >= 4.0 is present
    use junit4 provider
else
    use junit3.8.1

请注意,此算法的“else”部分也是常见问题解答:

您依赖于项目依赖项中存在的适当版本的 JUnit,否则 Surefire 可能会选择错误的提供程序。例如,如果您的一个依赖项引入了 JUnit 3.8.1,那么您就有风险选择 3.8.1 提供程序,它不支持注释或任何 4.x 特性。

使用mvn dependency:treePOM 依赖排序和/或排除传递依赖来解决此问题。

手动指定提供者

您还可以通过将其作为依赖项添加到 Surefire 本身来手动强制特定提供程序:

<plugins>
[...]
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <dependencies>
      <dependency>
        <groupId>org.apache.maven.surefire</groupId>
        <artifactId>surefire-junit47</artifactId>
        <version>3.0.0-M5</version>
      </dependency>
    </dependencies>
  </plugin>
[...]
</plugins>

使用此技术时,不会检查项目的类路径中是否存在正确的测试框架。未能添加正确的测试框架将导致构建失败。

并行运行测试

从 JUnit 4.7 开始,您可以并行运行测试。为此,您必须设置parallel参数,并且可以更改threadCountoruseUnlimitedThreads属性。例如:

<plugins>
    [...]
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M5</version>
        <configuration>
          <parallel>methods</parallel>
          <threadCount>10</threadCount>
        </configuration>
      </plugin>
    [...]
</plugins>

如果您的测试为该parallel属性指定任何值并且您的项目使用 JUnit 4.7+,那么您的请求将被路由到使用 JUnit JUnitCore 测试运行器的并发 JUnit 提供者。

这对于可能具有高并发性的慢速测试特别有用。

从 Surefire 2.7 开始,不需要额外的依赖项即可使用完整的并行选项集。从 Surefire 2.16 开始,引入了新的线程数属性,threadCountSuitesthreadCountClassesthreadCountMethods。此外,新属性parallelTestsTimeoutInSecondsparallelTestsTimeoutForcedInSeconds用于在超时后关闭并行执行,并且该属性parallel指定新值。

另请参阅分叉选项和并行测试执行

使用自定义侦听器和报告器

junit4 和 junit47 提供程序支持将自定义附加RunListeners到您的测试。

您可以像这样配置多个自定义侦听器:

<dependencies>
[...]
  <dependency>
    <groupId>your-junit-listener-artifact-groupid</groupId>
    <artifactId>your-junit-listener-artifact-artifactid</artifactId>
    <version>your-junit-listener-artifact-version</version>
    <scope>test</scope>
  </dependency>
[...]
</dependencies>
[...]
<plugins>
[...]
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
      <properties>
        <property>
          <name>listener</name>
          <value>com.mycompany.MyResultListener,com.mycompany.MyResultListener2</value>
        </property>
      </properties>
    </configuration>
  </plugin>
[...]
</plugins>

有关 JUnit 的更多信息,请参阅JUnit 网站

org.junit.runner.notification.RunListener您可以在单独的测试工件your-junit-listener-artifact中使用 scope=test 或在项目测试源代码中实现 JUnit 侦听器接口src/test/java。您可以通过参数过滤测试工件,以dependenciesToScan将其类加载到 surefire-junit* 提供程序的当前 ClassLoader 中。

由于 JUnit 4.12 线程安全监听器类应该被注释以org.junit.runner.notification.RunListener.ThreadSafe避免在 JUnit 中不必要的锁。

使用安全管理器(仅限 JUnit3)

只要forkCount不是 0 并且您使用 JUnit3,您就可以在启用 Java 安全管理器的情况下运行测试。安全管理器的类名必须作为系统属性变量发送给 JUnit3 提供者。

JUnit4 在内部使用与测试的安全管理器不兼容的机制,因此 Surefire 不支持这种使用 JUnit4 配置安全管理器的方法。

<plugins>
[...]
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M5</version>
        <configuration>
          <systemPropertyVariables>
            <surefire.security.manager>java.lang.SecurityManager</surefire.security.manager>
          </systemPropertyVariables>
        </configuration>
      </plugin>
[...]
</plugins>

使用安全管理器(所有提供商)

或者,您可以定义一个策略文件,允许所有提供程序使用 Surefire 运行并使用argLine参数和两个系统属性对其进行配置:

<plugins>
[...]
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M5</version>
        <configuration>
          <argLine>-Djava.security.manager -Djava.security.policy=${basedir}/src/test/resources/java.policy</argLine>
        </configuration>
      </plugin>
[...]
</plugins>

这种解决方案的缺点是策略变化也会影响测试,这使得安全环境不太现实。

使用 JUnit 类别

JUnit 4.8 引入了类别的概念。您可以通过使用该groups参数来使用 JUnit 类别。只要项目中的 JUnit 版本是 4.8 或更高,“groups”参数的存在就会自动让 Surefire 选择支持组的 junit47 提供程序。

<plugins>
[...]
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M5</version>
        <configuration>
            <groups>com.mycompany.SlowTests</groups>
        </configuration>
    </plugin>
[...]
</plugins>

这将只执行那些用@Category(com.mycompany.SlowTests.class)注解注解的测试和那些用@Category(com.mycompany.SlowerTests.class)如果类/接口SlowerTests是子类注解的测试SlowTests

    public interface SlowTests{}
    public interface SlowerTests extends SlowTests{}
    public class AppTest {
      @Test
      @Category(com.mycompany.SlowTests.class)
      public void testSlow() {
        System.out.println("slow");
      }

      @Test
      @Category(com.mycompany.SlowerTests.class)
      public void testSlower() {
        System.out.println("slower");
      }

      @Test
      @Category(com.cmycompany.FastTests.class)
      public void testSlow() {
        System.out.println("fast");
      }
    }

@Category注释也可以应用于类级别。

可以通过在参数中用逗号分隔多个类别来指定多个类别,groups在这种情况下,将执行带有任何类别注释的测试。

有关 JUnit 的更多信息,请参阅JUnit 网站

从 2.18.1 和 JUnit 4.12 版本开始,@Category注释类型自动从超类继承,请参阅@java.lang.annotation.Inherited. @Category确保测试类继承与超类中出现的 JUnit 4.12 或更高版本的注释一起仍然有意义。