合格的后端Coder都应该写好UT和Mock测试
作者 | S.L
来源 | http://r6d.cn/aaTem
关于测试
1 测试都包括哪些
广义的测试包括 UT、IT、压力测试、硬件测试等等,这里重点讨论 Unit Test 即单元测试。
2 啥是 UT
单元测试(又称为模块测试, Unit Testing)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。
简而言之就是覆盖你的代码的一些测试用例,不依赖于任何第三方的服务依赖,如 HTTP 接口、数据库连接等,只测试功能不依赖于环境,在任何时候人和机器上都可以 Pass。
3 为什么要写 UT
让你的代码质量更可靠&让你对代码结构更加敏感&迫使你写更优质的代码&…
4 为什么不写 UT
!${为什么要写 UT}
5 什么在阻止你写 UT
代码本身的原因
如果代码复杂度较高还缺少必要的抽象和拆分,就会让人对写 UT 望而生畏。
编码工作量的原因
无论是用什么样的单元测试框架,最后写出来的单元测试代码量也比业务代码只多不少,在不作弊的前提下要保证相关的测试覆盖率,大概要三倍源码左右的工作量。
难以维护的原因
更多的代码量,加上单测代码并不像业务代码那样直观,还有对单测代码可读性不重视的坏习惯,导致最终呈现出来的单测代码难以阅读,要维护更是难上加难。
6 合格的 UT 什么样
至少要满足:
测试的是一个代码单元内部的逻辑,而不是各模块之间的交互。
无依赖,不需要实际运行环境就可以测试代码。
运行效率高,可以随时执行。
Java 如何写 UT
Java 开发一般都是用 JUnit 或 TestNG,我们大多人还是使用 JUnit4。本文不讨论语法,只介绍一般性的使用规范。
7 命名
可以参考 7 Popular Unit Test Naming ( https://dzone.com/articles/7-popular-unit-test-naming )
8 Assertion
任何一个 UT 中需要至少包含一个 assert,用 System.out.println()来验证结果不符合 UT 的规范,一般都是验证方法的返回结果,如 assertEquals(200, statusCode)而不是 System.out.println(200==statusCode)。
Assertion 只能保证走过的分支的结果是否正确,无法保证一定是走过了某些分支。
9 为啥要 Mock
不用 Mock 我们自己也能实现测试(如匿名类),只不过对代码的要求非常高
10 Mock 框架
一些常用的 mock 库包括 Mockito、JMockIt、EasyMock、PowerMock…没有优劣没有好坏,只有合适与否。
比如我个人比较喜欢 Mockito:
第一它相对于其他几个老牌库来说比较新并且更新活跃,在 github 中引用的也最多
第二它的 fluent API 风格的代码可读性很高跟 JDK8 的 Stream 风格很像
第三它抽象出测试中的经典概念,如 when().thenReturn()、doThrow().when()、verify()、times()、never()以及各种注解很容易理解
11 什么样的方法需要 mock
任何被非本类的功能均需要 mock,如数据库访问、RPC 接口、外部引入的 jar 包等
环境变量、系统属性和方法
测试只测试当前类当前方法的功能,依赖方的功能由依赖方的 UT 来保证正确性,本层不负责验证
mock 本质上是一个 proxy,在需要提供功能的时候由开发者提供“伪实现”
12 什么样的方法不需要 mock
本类的需要测试的方法依赖的同类方法,该方法的正确性由该方法自身的 UT 来保证
静态方法,静态方法由自身的 UT 来保证功能的正确性
protected 方法是可以测试的,只要测试代码类和要测试的类在同一个 package 下面就可以
private 方法(有异议),我的看法是私有方法如果逻辑很多,应该重构出来提供 public 方法或者新的 Class 进行重构;如果逻辑不多仍然保证不了无 bug ,可以使用反射来测试。其实 private 方法的测试是需要通过对 public 方法的测试来完成的,因为 private 方法总是会被 public 方法调用的。还有一种测试方法就是放宽访问限制,private 方法改为 protected,并且用 guava 的 @VisibleForTesting 注解标注放宽权限的方法。
13 如何设计适合测试的接口
1.Dependency Injection
如果把一种依赖写死在方法里肯定不利于测试,如果该依赖是一种强引用第三方服务的 sdk 你就痛苦了,如配置类初始化时需要连接 zk 且无法注入
2.Abstraction
包括类的抽象、方法的提取,代码越精简,测试越方便、越快速、越容易暴露问题
3.开闭原则
面向扩展开发,面向修改闭合,不对老代码入侵,避免 UT 重复修改
4.慎重声明 static 方法
最好的 static 方法是完全不依赖任何第三方服务自己可以实现业务逻辑的代码,如果依赖第三方,使用 reference 传入而不是写死在 class 或 method 里
5.测试类而不是实现
单元测试测试的对象是类,测试类的功能在各种情况下是否符合预期,而不是测试实现。所以我们只需要测试能够跟其他类交互的 public 方法就可以了。这样的一个好处就是,如果哪天需要重构代码的实现,或者换一个算法实现某些方法,但功能不变的情况下,UT 是可以复用的。如果针对实现来测试,如果哪天要重构代码实现,那 UT 就会 fail 掉。
……待续……
测试覆盖率
一个仁者见仁智者见智的问题,不做深入讨论了。
个人建议工具方法(保证正确性以及边界条件不出错)、核心流程(复杂的条件判断尤其需要 UT 保证)需要重点覆盖,底层接口如 DAO、简单的 Service 封装可以不用写。
IDEA Plugin
推荐一个 JUnitGeneratorV2.0,可以通过 Command+N 来生成 Test 类或者直接在类名上使用 alt+enter 来生成。
总结
没有测不了的代码,只有测试不够方便的代码,大多源于设计不够合理。
写单元测试的难易程度跟代码的质量关系最大,并且是决定性的。项目里无论用了哪个测试框架都不能解决代码本身难以测试的问题,所以如果你遇到的是“我的代码里依赖的东西太多了所以写不出来单测”这样的问题的话,需要去看的是如何设计和重构代码,而不是这篇文章。
Reference
https://dzone.com/articles/7-popular-unit-test-naming ( https://dzone.com/articles/7-popular-unit-test-naming )
https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2 ( https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2 )
点击下方卡片关注我,订阅更多精彩内容
往期推荐
“智能”坐垫记录离座时间,是高科技福利还是又一个员工压榨机器?
Java延迟加载的最佳实践应用示例!
新年新气象,该换一波壁纸了!
不容错过的灰度发布系统架构设计
还在封装各种 Util 工具类?这个神级框架帮你解决所有问题!
阿里开源台柱 Ant Design 源码仓库被删了...
合格的后端Coder都应该写好UT和Mock测试相关推荐
- 后端开发都应该了解点接口的压力测试(Apache Bench版)
背景 小A:小B,最近调你的接口老是超时呀,8秒都还没返回结果,是不是有性能问题呀! 小B :我看看~~ 类似这样的对话,在现实中是时有发生的,不是特别严重的话,往往大家也不会去重视这个事. 尤其是在 ...
- 最近工程师怎么都在写公众号?这玩意到底能赚多少钱?
" 阅读本文大概需要 3 分钟. " 文章来源于进击的Coder,作者研究生小马 就是,前段时间嘛,公众号交流群,有一哥看我天天兢兢业业分享推送链接,提出了振聋发聩的问题 &quo ...
- 华为java一个月写多少行代码_[财经]阿里员工吐槽华为:面试官1万行代码都没写过? - 南方财富网...
5月7日,有疑似阿里员工在社交网络上爆料称,打算跳槽华为,但是去面试后,真的是太失望,因为面试官真的是太水了. 从这位网友晒出的帖子看,一名阿里的员工面试华为云后端开发的岗位,但过程并不顺利,因为面试 ...
- python编程可视化小程序_人人都可以写的可视化Python小程序第二篇:旋转的烟花...
兴趣是最好的老师 枯燥的编程容易让人放弃,兴趣才是最好的老师.无论孩子还是大人,只有发现这件事情真的有趣,我们才会非常执着的去做这件事,比如打游戏.如果编程能像玩游戏一样变得有趣,我相信很多人就特别愿 ...
- 后端接口都测试什么?要怎么测?
作者:Glen.He 来源:http://www.cnblogs.com/puresoul/ 本文主要分为两个部分: 第一部分: 主要从问题出发,引入接口测试的相关内容并与前端测试进行简单对比,总结两 ...
- 为什么程序员都不写文档?
[CSDN 编者按]对于程序员来说文档可能是他最大的软肋.一些被称之为高手的程序员,往往是文档方面的处理会偏弱.不管这个程序员是在大公司.还在小公司.不管程序是写文档的.还是不写文档的,大 ...
- 使用python完成的一个烟花小程序-人人都可以写的可视化Python小程序第二篇:旋转的烟花...
兴趣是最好的老师 枯燥的编程容易让人放弃,兴趣才是最好的老师.无论孩子还是大人,只有发现这件事情真的有趣,我们才会非常执着的去做这件事,比如打游戏.如果编程能像玩游戏一样变得有趣,我相信很多人就特别愿 ...
- 为什么从前那些.NET开发者都不写单元测试呢?
楔子 四年前我虽然也写了很多年代码,由于公司虽然规模不小,却并非一家规范化的软件公司,因此在项目中严格意义上来说并没有架构设计.也不写单元测试,后来有幸加入了一家公司,这家公司虽然也是一家小公司,但是 ...
- SPSS输出的结果都要写到文章中吗
SPSS输出的结果都要写到文章中吗 经常有人问到,SPSS输出的结果都要写到文章中吗?文章中应该写什么呢?比如,均值.中位数.众数.标准差.百分位数.最小值.最大值等等,都要出现在文章中吗?洋洋洒洒那 ...
最新文章
- mysql source导入报错ERROR 1366的解决方法
- 李飞飞点赞「ARM」:一种让模型快速适应数据变化的元学习方法 | 开源
- eclipse 安装svn插件
- SDUT OJ[3109] 买买买 背包 dp
- excel表中判断A列与B列内容是否相同,相同的话在C列按条件输出!
- word2003快速排版工具栏_干货分享 | 闲到在家数瓜子?——先把ID排版秘籍学了吧(上)...
- ubuntu上Nginx的配置
- FlexyPool如何同时支持连接代理和装饰器
- 单细胞转录组基本概念(一)
- CodeIgniter中引用某一个表情(smiley)
- c语言条件判断!,if条件判断语句,谁能帮我分析一下?
- go https 笔记
- DB2创建数据库示例
- 系统清理软件测试,系统垃圾清理有用吗?六大清理工具评测
- 华中师范大学计算机考研论坛,2020年华中师范大学计算机考研经验分享
- Failed to compile../public/UEditor/dialogs/template/template.html 1:0Module parse failed: Unexpec
- c语言程序设计基本模板,《C语言程序设计基础教程》试讲教案模板
- Google 地图- 基本地图类型
- 关于网络硬件配置出现问题,无法上网问题的解决
- 无人驾驶汽车技术之道路线识别
热门文章
- 转android项目开发 工作日志 2011.10.8--onConfigurationChanged屏幕改变事件
- DIY敷脸亲身示范做法 - 生活至上,美容至尚!
- 5107LiveChatCode
- linux c 延迟函数 sleep usleep 使用区别
- golang error类型详解
- 内核模块相关命令:lsmod,depmod,modprob,modinfo,insmod,rmmod
- 对 jiffies 溢出、回绕及 time_after 宏的理解
- TCP/IP详解--第二十章
- Android开发--用户定位服务--UserLocation
- CMake命令之list