一. 前言
同时将单元测试提前到编写正式代码进行(测试驱动开发),可以很好的提高对代码结构的设计。通过优先编写测试用例,可以很好的从用户角度来对功能的分解、使用过程和接口等进行设计,从而提高代码结构的高内聚、低耦合特性。使得对日后的需求变更或代码重构等更加高效、简洁。
因此编写单元测试对产品开发和维护、技术提升和积累具有重大意义!
二. 第一个单元测试
首先写一个单元测试,这样有助于对后面内容的理解与实践。
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),我们将立即处理