本文旨在从实践出发,引导开发者在Android项目中进行Mock单元测试。
什么是单元测试
单元测试由一组独立的测试构成,每个测试针对软件中的一个单独的程序单元。单元测试并非检查程序单元之间是否能够合作良好,而是检查单个程序单元行为是否正确。
为什么要进行单元测试
在敏捷开发大行其道的今天,由于时间紧,任务重,过分依赖测试工程师以及下列原因,导致单元测试不被重视,在开发流程中处于一个可有可无的尴尬境地。
浪费的时间太多
软件开发人员不应参与单元测试
我是很棒的程序员,不需要进行单元测试
不管怎样,集成测试将会抓住所有的Bug
单元测试效率不高
那么单元测试是否正的可有可无呢?No! No! No!
作为android客户端研发,在一个开发周期内,你负责的需求需要Web服务(API),和本地代码(JNI,Native Code)的支持,而你们的工作是同时进行的。
你的需求开发完成了,但是由于需要在特定条件下才能触发,而这些条件在开发过程中很难去模拟,导致需求无法在所有场景下进行充分测试。举个例子,假设你在室内开发一个地图导航的Android应用,你需要在导航过程中,前方出现车祸,积水,施工等多种状况,怎么办?
总结你过去的BUG,你会发现有些你以为写的很完善的逻辑,却在最后被发现有场景未覆盖,或者逻辑错误等问题。
测试工程师给你报了一个BUG,你改完提交了,但是之后由于Merge失误导致代码丢失,或者其他人的修改导致你的BUG再次出现。直到测试工程师再次发现该BUG,并再次给你提出。
你的开发进度很快,但是开发完成后,你会被BUG淹没。你持续不断的修改BUG,持续不断的加班,直至发布版本,身心俱疲。
以前明明很正常的功能,在本次开发周期内,突然不能正常使用了。
...
如果你也经常碰到以上问题,或者困扰,那么你需要持续不断的对项目进行单元测试。
Android单元测试简介
Android的单元测试分为两大类:
1.Instrumentation
通过Android系统的Instrumentation测试框架,我们可以编写测试代码,并且打包成APK,运行在Android手机上。
优点: 逼真
缺点: 很慢
代表框架:JUnit(Android自带),espresso
2.JUnit / Mock
通过JUnit,以及第三方测试框架,我们可以编写测试代码,生成class文件,直接运行在JVM虚拟机中。
优点: 很快。使用简单,方便。
缺点: 不够逼真。比如有些硬件相关的问题,无法通过这些测试出来。
代表框架: JUnit(标准),Robolectric, mockito, powermock
Android最佳Mock单元测试方案
我通过对比前辈们对各种单元测试框架的实践,总结出Android最佳Mock单元测试方案: Junit + Mockito + Powermock.(自己认证的...)
Junit + Mockito + Powermock 简介
众所周知,Junit是一个简单的单元测试框架。
Mockito,则是一个简单的用于Mock的单元测试框架。
那么为什么还需要Powermock呢?
EasyMock和Mockito等框架,对static, final, private方法均是不能mock的。
这些框架普遍是通过创建Proxy的方式来实现的mock。 而PowerMock是使用CGLib来操纵字节码而实现的mock,所以它能实现对上面方法的mock。
Junit + Mockito + Powermock 引入
由于PowerMock对Mockito有较强依赖,因此需要按照以下表格采用对应的版本。
Mockito
PowerMock
2.0.0-beta - 2.0.42-beta
1.6.5+
1.10.8 - 1.10.x
1.6.2+
1.9.5-rc1 - 1.9.5