概述

在使用Maven项目时,开发人员常常会遇到导致JUnit测试无法在构建过程中运行的错误。本文将探讨这些特定情况,并介绍如何解决这些问题。

2. 命名约定

Maven Surefire插件会在Maven构建生命周期的test阶段执行单元测试。重要的是,每当执行test目标(如运行mvn testmvn install)时,Surefire插件会被Maven生命周期隐式调用。

默认情况下,Surefire插件会自动包含以下通配符模式下的所有测试类:

  • **/Test*.java - 包含所有子目录和以“Test”开头的Java文件
  • **/*Test.java - 包含所有子目录和以“Test”结尾的Java文件
  • **/*Tests.java - 包含所有子目录和以“Tests”结尾的Java文件
  • **/*TestCase.java - 包含所有子目录和以“TestCase”结尾的Java文件

如果我们的测试类不遵循上述通配符模式,Maven将不会选择这些测试进行执行。然而,在某些情况下,可能需要遵循项目特定的命名模式,而非标准规范。在这种情况下,我们可以明确指定要包含(或排除)的测试和其他模式,以覆盖Surefire插件的行为。

例如,考虑以下pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M7</version>
            <configuration>
                <includes>
                    <include>**/*_UT.java</include>
                </includes>
                <excludes>
                    <exclude>**/BaseTest.java</exclude>
                    <exclude>**/TestsUtil.java</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

这里,我们看到除了标准命名约定外,还指定了要运行的具体测试,并排除了一些指示插件在测试阶段不应考虑的命名模式。

3. 错误的依赖关系

当使用JUnit 5平台时,我们需要至少添加一个TestEngine实现。 例如,如果我们想使用JUnit Jupiter编写测试,需要在pom.xml的依赖部分添加测试组件junit-jupiter-engine

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M7</version>
            <dependencies>
                <dependency>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-engine</artifactId>
                    <version>5.10.2</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

若要通过JUnit平台运行JUnit 3或4的测试,我们需要在依赖部分添加Vintage引擎:

<dependencies>
    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>5.10.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

4. 错误的测试文件夹

将测试放在错误的文件夹中也是导致它们未被考虑执行的原因。这主要源于某些IDE(如Eclipse)的默认类创建路径设置。

背景是,Maven定义了一个标准目录结构:

- src
  - main
    - java
    - resources
    - webapp
  - test
    - java
    - resources

- target

main目录是与应用程序本身相关的源代码根目录,而不是测试代码。test目录包含测试源代码。任何位于src/main/java目录下的测试都将被跳过。相反,所有测试和测试资源应分别放置在src/test/javasrc/test/resources文件夹下

例如,源类文件应放在这里:

src/main/java/Calculator.java

相应的测试类文件应放在这里:

src/test/java/CalculatorTest.java

5. 测试方法非public

Java的默认访问修饰符是package-private(包内可见)。这意味着没有额外访问修饰符的类仅对其所在包内的类可见。一些IDE在创建测试时会有标准配置,可能会将测试标记为包内可见。此外,测试方法可能意外地被标记为private

在JUnit 4之前,Maven只会运行标记为public的测试类。然而,对于JUnit 5+,这不是问题。但**实际的测试方法始终应标记为public**。

来看一个例子:

public class MySampleTest {
    @Test
    private void givenTestCase1_thenPrintTest1() {
        ...
    }
}

这里,我们注意到测试方法被标记为private。因此,Maven将不会考虑这个方法进行测试。将测试方法标记为public将使测试能够运行。

6. 打包类型

Maven提供了多种选项来打包应用,如jarwarearpom等。如果没有指定包装类型,它将默认为jar。每个包装类型都绑定到特定阶段的一系列目标。

将包装类型标记为pom将只将目标绑定到deployinstall阶段。在这种情况下,test阶段将被跳过。 这可能是测试无法按预期运行的情况之一。

有时,由于复制粘贴错误,Maven的包装类型可能被标记为pom

<packaging>pom</packaging>

要修复这个问题,我们需要指定正确的包装类型,例如:

<packaging>jar</packaging>

7. 总结

在这篇文章中,我们详细分析了Maven找不到JUnit测试执行的情况。首先,我们了解了命名约定如何影响测试执行。然后,讨论了在JUnit 5平台上运行测试所需的依赖。接下来,我们注意到了如何因为错误地将测试放在其他文件夹或测试方法标记为私有而导致测试无法运行。最后,我们了解到打包类型如何绑定到每个阶段的特定目标。