什么不是单元测试?很多同学容易将其他测试与单元测试搞混,最常见的是会启动Spring上下文的集成测试 。比如使用@SpringBootTest注解可以启动Spring上下文,这可以测试依赖是否正常注入等Spring的功能,但运行一次需要耗费很多时间(因为要启动Spring上下文),也并不是真正的“单元测试”,因为它依赖了Spring框架 。
如何写单元测试那具体如何写单元测试呢?我们业界有一个叫做「TDD」(测试驱动开发)的方法论 。TDD的核心在于“驱动”二字,它的理念是从测试视角出发,通过测试驱动出来产品代码 。而在测试金字塔中,单元测试与开发人员最息息相关,所以这里的“测试”一般是指的单元测试 。
TDD大概分这几个步骤:
- 理清需求
- 设计类和方法的出参和入参
- 写测试代码
- 驱动出产品代码
- 重构,循环3-5步 。
3-5步其实是一个循环的过程 。因为刚开始写代码可能并没有太注意代码的格式、风格、性能,一气呵成写得比较快,让测试通过 。等测试通过后,可以回过头来重构一下之前写的代码,重构后再跑一遍所有的单元测试,看是否有挂掉的单元测试,以此来检测重构是否对期望的输入输出有影响 。
单元测试的结构一个完整的单元测试,应该分为4个部分:
- 声明和参数
- 准备入参和mock
- 调用产品代码
- 验证,也叫断言
?一般来说,方法名需要尽可能可读,它可能比较长,但能够清晰地表述这个测试的意图,比如:
关于JUnit 5参数化测试,大家可以查看官方文档,也有对应的中文翻译,很方便阅读 。也可以去我的个人网站搜索《JUnit 5参数化测试》 。
?
@Testvoid shouldReturn5WhenCalculateSumGiven2And3() {}@Testvoid should_return_5_when_calculate_sum_given_2_and_3() {}复制代码
具体使用驼峰命名法还是下划线,根据自己团队的规范来就好,尽量所有测试风格保持一致 。(个人更喜欢下划线~)入参一般是基本类型或者POJO对象,有些参数可以抽成变量,后面在验证阶段可能用得上 。
如果产品代码有外部依赖,就需要用mock来消除外部依赖 。常见的Mock框架有EasyMock、「Mockito」等,大家可以对比一下各个mock框架的区别,选择一个合适的 。
很多同学刚开始写单元测试的时候不能理解为什么需要mock,觉得mock比较麻烦,甚至有点多此一举的感觉 。其实不然,mock的意义在于,你「可以保证你的测试只测试了你要测的那部分代码」 。这样如果测试不通过,你就可以知道一定是要测的那个方法有问题,不可能是外部依赖的问题,这样才能做到真正的“单元”化,才能保证每个测试足够小,足够纯粹 。
准备好入参和mock后,会显式地调用一下要测的那个方法,这个一般只有简单的一行 。
最后是验证,验证分为好几种,最常用的是验证出参是符合自己期望的 。也有时候会验证异常等边界情况 。JUnit等测试框架基本上自己带了验证的功能,但API都比较简单,个人感觉不是特别好用,推荐使用「AssertJ」,功能强大,API用起来也比较舒服 。
举个例子吧:
@Testvoid shouldReturnUserWithOrgInfoWhenLoginWithUserId() { String userId = "userId"; String orgId = "orgId"; User user = UserFactory.getUser(userId); Org org = OrgFactory.getOrg(orgId); given(orgService.getOrgById(orgId)).willReturn(org); UserInfo userInfo = userService.login(userId); assertEquals(org, userInfo.getOrg());}复制代码
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 从天庭开始签到 天墉城签到三百年
- s10赛季开始 s10赛季奖励截止日期
- 拜腾汽车背后股东 我从拜腾汽车辞职
- 来说说怎样可以养好一条金毛? 金毛从小到大的成长过程
- 诺亚方舟之谜 诺亚之心怎么没了
- 求职|从高薪到无业游民,是什么让这群人转行,另谋生路?这4点是关键
- 会稽山的风土人情,茶从物质层次上升到了文化内涵的高度
- 盒马几点开始七折 盒马几点钟开始打折
- 从党的什么开始中国进入了改革开放的新时期a,从党的什么开始中国进入了改革开放的新时代?
- 拒绝衰老从杯茶开始,紫砂壶岁寒三友壶简介