本文首先在理论上归纳了单元测试在宏观和微观层面要遵循的基本原则,以及测试覆盖率的要求和评价维度。然后具体阐述了笔者实战中总结的基于Junit + Mockito 的单元测试框架和具体实施方法,并给出了相应的demo代码。
本文主要参考和引用了《码出高效:Java开发手册》,Junit5、mockito等官方文档以及若干篇相关博客的内容,具体可见文末参考链接部分。
宏观层面:AIR原则
- A:Automatic(自动化)
全自动执行,输出结果无需人工检查,而是通过断言验证。 - I:Independent(独立性)
分层测试,各层之间不相互依赖。 - R:Repeatable(可重复)
可重复执行,不受外部环境( 网络、服务、中间件等)影响。
微观层面:BCDE原则
- B: Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
- C: Correct,正确的输入,并得到预期的结果。
- D: Design,与设计文档相结合,来编写单元测试。
- E : Error,单元测试的目标是证明程序有错,而不是程序无错。为了发现代码中潜在的错误, 我们需要在编写测试用例时有一些强制的错误输入(如非法数据、异常流程、非业务允许输入等)来得到预期的错误结果。
Mock
由于单元测试只是系统集成测试前的小模块测试,有些因素往往是不具备的,因此需要进行Mock。例如:
- 功能因素。比如被测试方法内部调用的功能不可用。
- 时间因素。比如双十一还没有到来,与此时间相关的功能点。
- 环境因素。政策环境,如支付宝政策类新功能,多端环境, 如PC 、手机等。
- 数据因素。线下数据样本过小,难以覆盖各种线上真实场景。
- 粗粒度覆盖:类覆盖率和方法覆盖率应达到100%。
- 细粒度覆盖:行覆盖、分支覆盖、条件判定覆盖、路径覆盖等,相应的覆盖率应考虑上述原则与因素。
底层测试框架:junit
Junit主流还是junit4,最新版本是4.12(2014年12月5日),现在最新的是junit5(JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage)。junit5正式版本的发布日期是2017年9月11日,目前最新的版本是5.5.2(2019年9月9日)。我们项目底层选择了junit5。
Mock工具
- 方法:mockito
目前,在 Java 阵营中主要的 Mock 测试工具有 Mockito、JMock、EasyMock 等。我们选择了功能更强大且容易上手的Mockito。
另外,Mockito不支持static的的方法的mock,要使用PowerMock来模拟。但是PowerMock似乎现在还不支持junit5,我们没有使用。 - 模拟数据生成:jmockdata
- Redis:redis-mock
- 数据库:h2
- 接口:MockMVC
该部分以Spring Boot项目为例,介绍单元测试中主要碰到的需求与问题以及相应的实施方法。开发环境选择IntelliJ IDEA 2018。
测试需求分析
Junit5的基本使用
Maven导入依赖
常用注解

最基本的测试代码
参数化测试
使用@ParameterizedTest注解,参数化测试使得测试可以测试多次使用不同的参数值。
参数源:
@ValueSource是最简单的来源之一。它允许你指定单个数组的文字值,并且只能用于为每个参数化的测试调用提供单个参数。
@NullSource注解用来给参数测试提供一个null元素,要求传参的类型不能是基本类型(基本类型不能是null值)
@EmptySource为java.lang.String, java.util.List, java.util.Set, java.util.Map, primitive arrays等类型提供了空参数。
@NullAndEmptySource 注解为上边两个注解的合并。
@EnumSource能够很方便地提供Enum常量。该注解提供了一个可选的names参数,你可以用它来指定使用哪些常量。如果省略了,就意味着所有的常量将被使用。
重复测试
@RepeatedTest中填入次数可以重复测试。
条件测试
测试执行顺序
可以在类上标注@TestMethodOrder来声明测试方法要有执行顺序,里边可以传入三种类Alphanumeric、OrderAnnotation、Random,分别代表字母排序、数字排序、随机。然后对方法加@Order注解里边传入参数决定顺序。
断言
动态测试
JUnit Jupiter还引入了一种全新的测试编程模型。
这种新类型的测试是一种动态测试,它是由一个工厂方法在运行时生成的,该方法用@TestFactory注释。与@Test方法相比,@TestFactory方法本身不是测试用例,而是测试用例的工厂。 因此,动态测试是工厂的产物。
同一个@TestFactory所生成的n个动态测试,@BeforeEach和@AfterEach只会在这n个动态测试开始前和结束后各执行一次,不会为每一个单独的动态测试都执行。
Mockito的基本使用
Maven导入依赖
基于Mockito的service层测试
controller层测试
DAO层测试
模拟数据生成
JmockData 2.0:https://github.com/jsonzou/jmockdata-demo
测试报告生成
命名规范
- 测试方法命名
(1)原方法 or 原方法+Test
(2) test + 待测场景和期待结果的命名方式
例如,testDecodeUserTokenSuccess
(3)“should . … When”结构
例如,shouldSuccessWhenDecodeUserToken -
- 测试类和方法名称呈现
@DisplayName
- 测试类和方法名称呈现
覆盖率统计
cobertura:https://www.jianshu.com/p/d6c
报告美化
《JUnit报告美化——ExtentReports》:https://www.cnblogs.com/goldsking/p/7598085.html
[1]《码出高效:Java开发手册》:https://book.douban.com/subject//
[2] 《JUnit 5 User Guide》:https://junit.org/junit5/docs/current/user-guide
[3] JUnit5用户手册:https://www.cnblogs.com/followerofjests/p/10466070.html
[4] 单元测试实践(SpringCloud+Junit5+Mockito+DataMocker):https://www.cnblogs.com/pluto4596/p/11703382.html
[5] Mockito 中文文档 ( 2.0.26 beta ):https://github.com/hehonghui/mockito-doc-zh
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/11191.html