Why Maven Doesn’t Find JUnit Tests to Run – 为什么Maven找不到要运行的JUnit测试?

最后修改: 2022年 7月 22日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

When working with Maven projects, it’s common for a developer to make a mistake that results in JUnit tests not running during a build. There are a variety of reasons why Maven might not find JUnit tests to run. In this tutorial, we’ll look at those specific cases and see how to fix them.

在处理Maven项目时,开发人员经常会犯错,导致JUnit测试在构建过程中无法运行。Maven可能找不到要运行的JUnit测试,原因有很多。在本教程中,我们将探讨这些特定的情况,并看看如何解决这些问题。

2. Naming Conventions

2.命名规则

Maven Surefire plugin executes unit tests during the test phase of the Maven build lifecycle. Importantly, the Surefire plugin is called implicitly by the Maven life cycle whenever the test goal is executed — for example, when running ‘mvn test‘ or ‘mvn install‘.

Maven Surefire插件在Maven构建生命周期的test阶段执行单元测试。重要的是,只要执行test目标,Maven生命周期就会隐式调用Surefire插件–例如,运行’mvn test‘或’mvn install‘时。

By default, the Surefire Plugin will automatically include all the test classes with the following wildcard patterns:

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

  • “**/Test*.java” – includes all of its subdirectories and all Java filenames that start with “Test”
  • “**/*Test.java” – includes all of its subdirectories and all Java filenames that end with “Test”
  • “**/*Tests.java” – includes all of its subdirectories and all Java filenames that end with “Tests”
  • “**/*TestCase.java” – includes all of its subdirectories and all Java filenames that end with “TestCase”

So, if our tests don’t follow the above wildcard patterns, Maven isn’t going to pick these tests to run. However, there are cases where there could be project-specific naming patterns to be followed instead of these standard conventions. In those cases, we can override the Surefire Plugin by explicitly specifying the tests that we want to include (or exclude) and other patterns.

因此,如果我们的测试不遵循上述通配符模式,Maven就不会选择这些测试来运行。然而,在某些情况下,可能需要遵循特定项目的命名模式,而不是这些标准惯例。在这种情况下,我们可以通过明确指定我们想包括(或排除)的测试和其他模式来覆盖Surefire插件。

For example, let’s consider the following pom.xml:

例如,让我们考虑以下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>

Here, we can see that in addition to the standard naming conventions, we’ve included specific tests to run. Also, we’ve excluded certain naming patterns that instruct the plugin not to consider those tests during the test phase.

在这里,我们可以看到,除了标准的命名惯例外,我们还包括要运行的特定测试。此外,我们还排除了某些命名模式,指示插件在测试阶段不要考虑这些测试。

3. Incorrect Dependencies

3.不正确的依赖关系

When using the JUnit 5 platform, we need to add at least a single TestEngine implementation. For example, if we want to write tests with JUnit Jupiter, we need to add the test artifact junit-jupiter-engine to the dependencies in pom.xml:

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

<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.4.0</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

If we want to write and execute JUnit 3 or 4 tests via the JUnit Platform, we need to add the Vintage Engine to the dependencies section:

如果我们想通过JUnit平台编写和执行JUnit 3或4测试,我们需要将Vintage引擎添加到依赖项中。

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

4. Incorrect Test Folder

4.测试文件夹不正确

Placing tests in the wrong folder is another reason why the tests aren’t considered for execution. This occurs mainly due to the default class creation path setting in some IDEs (such as Eclipse).

将测试放在错误的文件夹中是另一个导致测试不被考虑执行的原因。这主要是由于一些IDE(如Eclipse)中默认的类创建路径设置而发生的。

To give some background, Maven defines a standard directory structure:

介绍一下背景,Maven定义了一个标准的目录结构。

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

- target

The main directory is the root directory for source code related to the application itself, not the test code. The test directory contains the test source code. Any tests placed under the src/main/java directory will be skipped. Instead, all the tests and test resources should be placed under the src/test /java and src/test/resources folder, respectively.

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

For example, the source class file should be placed here:

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

src/main/java/Calculator.java

And, the corresponding test class file should be placed here:

而且,相应的测试类文件应该放在这里。

src/test/java/CalculatorTest.java

5. Test Method Not public

5.测试方法不公开

The default access modifier in Java is package-private. This means that all classes created without additional access modifiers are visible only to the classes in the same package. Some IDEs have standard configurations so that, while creating tests, they will be marked as package-private. Also, the test method could have been marked as private by mistake.

Java中默认的访问修饰符是package-private。这意味着所有创建的类在没有附加访问修饰符的情况下,只对同一包中的类可见。一些IDE有标准的配置,因此在创建测试时,它们将被标记为包-私有。另外,测试方法也可能被错误地标记为private

Until JUnit 4, Maven will only run the test classes which are marked as public. We should note, though, that this won’t be an issue with JUnit 5+. However, the actual test methods should always be marked as public.

在JUnit 4之前,Maven只运行被标记为public的测试类。不过,我们应该注意到,这在JUnit 5+中不会成为一个问题。然而,实际的测试方法应始终标记为public

Let’s look at an example:

我们来看看一个例子。

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

Here, we can notice that the test method is marked as private. Consequently, Maven won’t consider this method for test execution. Marking the test method as public will enable the test to run.

在这里,我们可以注意到,测试方法被标记为private。因此,Maven不会考虑将该方法用于测试执行。将测试方法标记为public,就可以运行测试了。

6. Packaging Type

6.包装类型

Maven provides multiple options to package the application. The popular packaging types are jar, war, ear, and pom. If we don’t specify a packaging value, it will default to jar packaging. Each packaging contains a list of goals to bind to a particular phase.

Maven为打包应用程序提供了多种选择。常用的打包类型有 jarwarearpom。如果我们没有指定一个打包值,它将默认为jar打包。每个包装都包含一个目标列表,以绑定到一个特定的阶段。

Marking the packaging type as pom will only bind goals to the deploy and install phases. The test phase will be skipped in this case. This could be one of the cases where the tests don’t run as expected.

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

Sometimes, due to a copy-paste error, the Maven packaging type could’ve been marked as pom:

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

<packaging>pom</packaging>

To fix this, we need to specify the correct packaging type. For example:

为了解决这个问题,我们需要指定正确的包装类型。比如说。

<packaging>jar</packaging>

7. Conclusion

7.结语

In this article, we examined specific cases in which Maven doesn’t find JUnit tests to run.

在这篇文章中,我们研究了Maven找不到JUnit测试运行的具体案例。

First, we saw how the naming conventions could impact the test execution. Next, we discussed the dependencies to add for the tests to execute on the JUnit 5 platform. Further, we also noted how incorrect placement of tests in a different folder or having private test methods could prevent the tests from being run. Finally, we saw how the packaging type is bound to specific goals in each phase.

首先,我们看到了命名规则如何影响测试的执行。接下来,我们讨论了在JUnit 5平台上执行测试时需要添加的依赖性。此外,我们还注意到,在不同的文件夹中不正确地放置测试,或有私有的测试方法,会阻止测试的运行。最后,我们看到包装类型是如何与每个阶段的具体目标相联系的。