golang 单元测试踩坑系列(一)
迫切的业务需求
在业务开发的过程中,老旧代码变成了新功能开发和测试的最大阻碍,人员变动以及。基于历史代码的功能修改可能会带来副作用,进而影响用户体验(绩效)。
面临困难
老代码对接口的使用非常少
业务逻辑中存在大量网络调用
改造
熟悉业务
熟悉业务是需要找到对外部依赖最少的代码,从依赖最少的代码入手可以极大减少初期编写单元测试的工作量。外部依赖代码主要是对数据库的操作、接口调用等等。将对外的依赖抽离出来,是最简单的一种处理方式。
逐步改进
将网络调用通过接口形式调用
假设有一个场景,需要通过接口获取一个用户的信息,并判断用户的性别,代码如下(在业务场景中这样的代码非常常见):
如果需要编写单元测试,步骤如下
首先需要将
GetUserInfo
抽离出来,尽量不要在代码中直接调用包含网络请求的函数。修改完成的代码如下,定义一个
ApiUser
的接口,实现该接口需要实现GetUserInfo
方法。在
Service
中嵌入一个实现ApiUser
的对象,方便我们后续使用 mock 将模拟数据注入到Service
对象中(关于 mock 我们后续后有详细分析)。mock 简单来说就是,我们可以使用一个实现了
ApiUser
接口的类型放入到Service
中,而这个 ApiUser 对象返回*User
时可以不需要网络请求,只是简单伪装返回数据。在测试的时候我们就可以不需要依赖外部的服务来实现单元测试。
把
ApiUser
嵌入到调用类型中实际上也是一种妥协的。IsBoy(userid int)
这个方法可能在多个地方被同时调用,如果在方法的参数中传入ApiUser
对象也是不太现实(需要注意的是,初始化Service
对象需要记得设置ApiUser
的值)另外一种方式是使用全局变量,但个人不太推荐。
编写逻辑测试
定义一个apiUserFake
类型,实现GetUserInfo
方法,用于模拟实际的网络请求
假设源码文件为user.go
,在当前目录下增加一个user_test.go
一个简单的逻辑测试完成。
这种方式写单元测试很繁琐,后面提到的 mock 就是为了解决这种问题而出现的。
编写接口测试
接口测试需要启动服务器,并且将请求指向接口地址。
接口测试实际是作为验证外部依赖正确性的一种方式,不应该完全相信被调用方。
提高代码覆盖率
增加测试用例。。。
对您有帮助可以帮忙关注下公众号:
版权声明: 本文为 InfoQ 作者【geange】的原创文章。
原文链接:【http://xie.infoq.cn/article/15e892000d1db27371b8dac5d】。文章转载请联系作者。
评论