Java服务端单元测试指南(1)

发表于:2022-4-24 09:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:墨源    来源:网络

  一. 前言
  单元测试并不只是为了验证你当前所写的代码是否存在问题,更为重要的是它可以很大程度的保障日后因业务变更、修复Bug或重构等引起的代码变更而导致(或新增)的风险。
  同时将单元测试提前到编写正式代码进行(测试驱动开发),可以很好的提高对代码结构的设计。通过优先编写测试用例,可以很好的从用户角度来对功能的分解、使用过程和接口等进行设计,从而提高代码结构的高内聚、低耦合特性。使得对日后的需求变更或代码重构等更加高效、简洁。
  因此编写单元测试对产品开发和维护、技术提升和积累具有重大意义!
  二. 第一个单元测试
  首先写一个单元测试,这样有助于对后面内容的理解与实践。
  2.1 开发环境
  IntelliJ IDEA
  IntelliJ IDEA默认自带并启用TestNG和覆盖率插件:
  ·TestNG
  在设置窗口查看TestNG插件是否安装与启用:
  · 覆盖率
  同样,查看覆盖率插件可以搜索“Coverage”。IntelliJ IDEA的覆盖率统计工具有三种,JaCoCo、Emma和IntelliJ IDEA自带。
  · 变异测试
  同样,查看并安装变异测试插件可以搜索“PIT mutation testing”。
  Eclipse
  Eclipse 需要自行安装单元测试相关插件:
  · TestNG
  执行TestNG单元测试的插件。可在Eclipse Marketplace搜索“TestNG”安装:
  · 覆盖率
  获取单元测试覆盖率的插件。可在Eclipse Marketplace搜索“EclEmma”安装:
  · 变异测试
  同样,查看并安装变异测试插件可以搜索“Pitclipse”。
  2.2 Maven依赖
  在这里搜索JAR包的新版本
  · TestNG
  <dependency>
     <groupId>org.testng</groupId>
     <artifactId>testng</artifactId>
     <version>${testng.version}</version>
     <scope>test</scope>
  </dependency>

  · JMockit
  <dependency>
     <groupId>org.jmockit</groupId>
     <artifactId>jmockit</artifactId>
     <version>${jmockit.version}</version>
     <scope>test</scope>
  </dependency>
  <dependency>
     <groupId>org.jmockit</groupId>
     <artifactId>jmockit-coverage</artifactId>
     <version>${jmockit.version}</version>
     <scope>test</scope>
  </dependency>

  · Spring Test
  <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-test</artifactId>
     <version>${spring.version}</version>
     <scope>test</scope>
  </dependency>
  <dependency>
     <groupId>org.kubek2k</groupId>
     <artifactId>springockito</artifactId>
     <version>${springockito.version}</version>
     <scope>test</scope>
  </dependency>
  <dependency>
     <groupId>org.kubek2k</groupId>
     <artifactId>springockito-annotations</artifactId>
     <version>${springockito.version}</version>
     <scope>test</scope>
  </dependency>

  · 其他(或许需要)
  <dependency>
     <groupId>org.apache.tomcat</groupId>
     <artifactId>tomcat-servlet-api</artifactId>
     <version>${tomcat.servlet.api.version}</version>
     <scope>test</scope>
  </dependency>

  2.3 创建单元测试
  下面介绍通过IDE自动创建单元测试的方法(也可手动完成):
  IntelliJ IDEA
  1.在被测试类的类名代码行上(“class”关键字代码行)按下Alt + Enter快捷键(或将鼠标指针停留其上,待出现黄色灯泡图标后,鼠标点击其下拉菜单。),在弹出的菜单上选择Create Test选项:
  2.在弹出的窗口中选择“TestNG”并选择要创建的单元测试方法后点击“OK”按钮创建单元测试。(中间的类名、包名以及是否要创建“setUP”和“tearDown”方法,可根据自己的情况选择。)
  3.创建后的单元测试在Maven工程的test目录下生成测试类:
  Eclipse:
  1.在被测试类的文件上右键菜单“New -> Other”;
  2.在弹出的窗口中搜索“Test”,选择“TestNG class”后点击“Next”按钮;
  3.在窗口中选择要创建的测试方法后点击“Next”按钮;
  4.根据自己的情况设置包名、类名和Annotations等。
  示例代码
  可参考下例代码编写单元测试:
  package org.light4j.unit.test;
  import mockit.Expectations;
  import mockit.Injectable;
  import mockit.Tested;
  import org.testng.Assert;
  import org.testng.annotations.Test;
  import wow.unit.test.remote.UserService;
  import java.util.List;
  /**
   * 单元测试demo
   *
   * @author jiazuo.ljz
   */
  public class BookServiceTest {
      /**
       * 图书持久化类,远程接口
       */
      @Injectable
      private BookDAO bookDAO;
      /**
       * 用户服务,远程接口
       */
      @Injectable
      private UserService userService;
      /**
       * 图书服务,本地接口
       */
      @Tested(availableDuringSetup = true)
      private BookService bookService;
      /**
       * 测试根据用户的Nick查询用户的图书列表方法
       * 其中“getUserBooksByUserNick”方法最终需要通过UserID查询DB,
       * 所以在调用此方法之前需要先对UserService类的getUserIDByNick方法进行Mock。
       */
      @Test
      public void testGetUserBooksByUserNick() throws Exception {
          new Expectations() {
              {
                  userService.getUserIDByNick(anyString); // Mock接口
                  result = 1234567; // Mock接口的返回值
                  times = 1; // 此接口会被调用一次
              }
          };
          List<BookDO> bookList = bookService.getUserBooksByUserNick("moyuan.jcc");
          Assert.assertNotNull(bookList);
      }
  }

  2.4 运行单元测试
  IntelliJ IDEA
  1.在测试方法上鼠标右键“Run ‘testMethod()’”,在同级菜单下面还有“Debug”和“Coverage”:
  注:也可点击工具栏选项运行,从左至右依次是:运行、调试、覆盖率运行,可根据自己的需要选择:
  2.点击“运行”:
  左侧框:单元测试类区域
  底侧框:单元测试打印输出的内容和运行结果
  Eclipse
  1.在测试方法上鼠标右键“Run As -> TestNG Test”,在同级菜单下面还有“Debug As”和“Coverage As”:
  注:也可点击工具栏选项运行,从左至右依次是:覆盖率、调试、运行运行。
  2.点击“运行”:
  左侧框:单元测试运行结果
  底侧框:单元测试打印输出的内容
  Maven
  ·执行目录下所有单元测试,进入工程目录后执行:mvn test
  · 执行具体的单元测试类,多个测试类可用逗号分开:mvn test -Dtest=Test1,Test2
  · 执行具体的单元测试类的方法:mvn test -Dtest=Test1#testMethod
  · 执行某个包下的单元测试:mvn test -Dtest=com/alibaba/biz/*
  · 执行ANT风格路径表达式下的单元测试:mvn test -Dtest=**/*Test或mvn test -Dtest=**/???Test
  · 忽略单元测试:mvn -Dmaven.test.skip=true
  2.5 单元测试覆盖
  IntelliJ IDEA
  1.运行
  点击“覆盖率运行”:
  左侧框1:被测试类和覆盖率
  左侧框2:单元测试类区域
  中间框:被测试类代码。绿色行表示被覆盖,红色行表示末被覆盖
  右侧框:所有类被覆盖情况,双击包名可以查看详细类覆盖情况
  底侧框:单元测试打印输出的内容和运行结果
  2.输出报告
  运行过程以及结果输出的窗口中有一行“JMockit: Coverage report written to”,是JMocit创建的覆盖率报告文件目录:
  Eclipse
  1.运行
  点击“覆盖率运行”(可参看“运行单元测试”一节):
  左侧框:运行结果
  中间框:被测试类代码。绿色行表示被覆盖,红色行表示末被覆盖
  右侧框:所有类被覆盖情况,双击包名可以查看详细类覆盖情况(相比IntelliJ IDEA的Package窗口缺少了类覆盖率数据)
  底侧框:单元测试打印输出的内容
  2.输出报告
  运行过程以及结果输出的窗口中有一行“JMockit: Coverage report written to”,是EclEmma创建的覆盖率报告文件目录。
  覆盖率报告
  ·打开目录下的“index.html”文件
  · 点击查看类文件详细覆盖情况
  2.6 变异测试
  变异测试是覆盖率的一个很好的补充。相比覆盖率,它能够使单元测试更加健壮。(具体可见5.4节)
  IntelliJ IDEA
  1. 创建运行
  点击运行的下拉选项,选择“Edit Configurations…”打开“Run/Debug Configurations”窗口:
  点击左上角“+”号后选择添加“PIT Runner”:
  注意“Target classes 和 Source dir”两项与单元测试类包和模块路径的准确对应,确认无误后点击“OK”按钮确认创建。
  2. 运行
  创建完成后,直接点击工具条“运行”图标即可运行。
  3. 输出报告
  运行过程以及结果输出的窗口中最后一行“Open report in browser”即为插件创建的报告连接。
  点击即可打开报告。
  Eclipse
  1. 运行
  在单元测试类上右键菜单“Run As” -> “2 PIT Mutation Test”,即可运行。
  运行过程以及结果输出的窗口。
  2. 输出报告
  可在此窗口中查看变异测试发现的可能存在的代码缺陷:(这点比IDEA的PIT插件做的要好)
  可在此窗口中查看测试报告。
  为今后更好的开展与落实单元测试,请继续阅读下面内容。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号