Maven 单元测试

在我们平时开发的过程中,测试环节是永远不能避免的。那我们如何能够快速的进行单元测试呢,如何更方便的看到测试结果呢?在这个过程中,Maven 也能够为我们提供帮助,那我们来看看 Maven 如何在测试环节来辅助我们的。

1. 使用 Maven 进行单元测试

1.1 添加测试代码

这里面我们在 mall-order 模块中增加生成订单的方法,这个方法调用后会生成一个 OrderEntity 对象,里面包括订单编号(orderNuM)和订单所有者(orderOwner)两个字段。(这里我们仅仅是用来模拟单元测试,对业务的具体逻辑不做过多纠结)

首先,我们在 mall-order 模块的 pom.xml 文件中添加需要的依赖。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
</dependency>

添加依赖后,我们在项目中创建 service 目录和 entity 目录,分别用于存放项目的服务层代码和实体类。

在项目中添加对应的 service 和 entity

并且在对应的测试目录中,增加该服务层代码的测试类 OrderServiceTest

完成后,我们可以执行该测试用例,来调试 OrderService 中的 generateOrder 方法。

从调试结果来看,我们的方法被成功调用,并且没有异常。

1.2 借助 Maven 进行单元测试

后来,随着我们项目的不断进行,我们开发的功能也随之不断增多,相应的,不同功能的测试用例也在不断的增多。这个时候,如果单纯的靠开发人员手工去点击每一个测试用例,这显然是不合理的。

那么我们就可以借助 Maven 来帮助我们做这件事情,来进行自动化的单元测试。

例如在 mall-order 模块下, 我们想要执行所有的单元测试用例,那么我们只需要进入到该模块的根目录下,执行 mvn test 命令即可。

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mic.tech:mall-order >-----------------------
[INFO] Building mall-order 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mall-order ---
[INFO] Surefire report directory: D:codemall-aggregatemall-ordertargetsurefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mic.tech.OrderServiceTest
...
Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.333 s
[INFO] Finished at: 2020-05-20T23:37:40+08:00
[INFO] ------------------------------------------------------------------------

从执行结果,我们可以看出,一共执行了三个测试用例,没有失败,也没有报错的情况出现。

2. 跳过测试

2.1 指定测试用例进行测试

其实每一项新的操作一般都会伴随一些问题产生。例如,我们在实际的开发过程中,有些时候只是改动了一处代码,但是如果直接执行 mvn test 命令的话,会将整个项目的测试用例全部都执行一遍,这对于我们来说,是有些得不偿失的,没必要因为一处改动,而去测试其他几十个或者几百个测试用例。

那我们应该怎么办呢? 这里我们为了演示,写了两个测试类,OrderServiceTestOrderService2Test,其中第一个类中,有两个测试用例,第二个类中,只有一个测试用例。

这时候,我们修改了第二个类中测试用例对应的方法,需要重新进行单元测试。我们可以直接执行命令:mvn test -Dtest=OrderService2Test

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mic.tech:mall-order >-----------------------
[INFO] Building mall-order 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mall-order ---
[INFO] Surefire report directory: D:codemall-aggregatemall-ordertargetsurefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mic.tech.OrderService2Test
...
Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.261 s
[INFO] Finished at: 2020-05-21T22:17:47+08:00
[INFO] ------------------------------------------------------------------------

从结构来看,我们这里只执行了第二个测试类中的测试用例。

2.2 跳过测试

换到另外一个场景,构建项目的时候。在平时的开发过程中,我们经常会使用mvn package构建项目,但是如果这个项目比较庞大,测试用例会非常多,那么执行测试用例的过程就会非常耗时。那怎么办呢,test 阶段在 package 阶段之前,如果直接执行 package 阶段,test 阶段势必会被执行到。

这个时候我们可以跳过测试来构建项目。(当然,这样的做法是不被建议的)

在执行构建命令的时候,添加参数来指定跳过测试即可,mvn package -DskipTests 或者 mvn package -Dmaven.test.skip=true

这两个命令虽然都能够在构建项目的时候跳过测试,但还是有些区别的。

  • -DskipTests: 会编译测试类;
  • -Dmaven.test.skip=true: 不会编译测试类。

3. 测试报告

Maven 的默认配置中,会在 targetsurefire-reports 目录下生成测试报告。

我们执行 mvn clean test,就可以观察到该目录生成。

我们可以在 txt 格式的文档中看到生成的测试报告。这里的测试报告基本上和控制台输出的内容是类似的。

大家可能也注意到了,我们在执行测试用例的时候,同时生成了两种类型的文件,一种是 txt 格式,另一个则是 XML 格式。

  • txt 格式: 为了让执行测试用例的开发者更加直观的看到测试用例的运行结果;
  • XML格式: 更多的是为了支持其他工具的解析。

4. maven-surefire-plugin

说了这么多,其实 Maven 之所以可以帮助我们自动执行测试用例,还是依靠 maven-surefire-plugin 插件来实现的。在学过 Maven 的生命周期之后,我们知道一个插件的功能都是通过目标来实现的,而不同的目标则会和生命周期中的不同阶段进行绑定。这里,生命周期中的 test 阶段就是和 maven-surefire-plugin 插件的 test 目标进行绑定的。

对于 Maven 来说,我们可以不指定或者显示的声明该插件。

在显示声明的时候,我可以通过添加 configuration 的方式来实现刚刚执行命令的效果。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.17</version>
            <configuration>
            	<skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>

例如我们在 configuration 中添加 skipTests 节点,则可以默认跳过测试。当我们再次执行mvn package命令构建项目的时候,test 阶段是不会被执行的。

当然,我们也可以在 configuration 中添加 include 节点和 exclude 节点,来控制执行的测试类。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.17</version>
    <configuration>
        <includes>
        	<include>**/OrderServiceTest.java</include>
        </includes>
        <excludes>
        	<exclude>**/OrderService2Test.java</exclude>
        </excludes>
    </configuration>
</plugin>

此时,我们再次执行mvn test的时候会发现只有OrderServiceTest.java类中的测试用例被执行了。

5. 小结

在本节的学习中,我们简单介绍了如何编写测试用例,Maven 如何自动的执行测试用例,以及在执行测试用例的过程中的一些技巧,比如跳过测试。最后我们还介绍了 maven-surefire-plugin 的简单使用。通过本节的学习,我们可以使用 Maven 轻松的进行自动化测试。