单元测试不好搞阿,虽然从TDD角度出发,可测性强的代码很大程度上就代表着好的设计,但是有些情况也是没办法的,比如单例模式,比如Static方法,比如Final类,传统的Mock技术是没办法解决这些问题的,而如果单纯为了测性去修改代码,这会大大破坏代码的整体设计,所以开发不愿意搞单元测试,而测试人员更拿这不可测的代码束手无策。

好在,在Java领域,有了PowerMock

PowerMock简介

PowerMock使用自定义的类加载器和字节码操作技术,从而使得我们能够Mock: Static方法,构造函数, Final的类和方法,Private的方法,即使是静态初始化也不在话下。PowerMock的强大是不言而喻的,它不需要我们对IDE有任何的修改就可以直接使用,而且对持续集成的配置也没有任何额外影响。PowerMock是对现有Mock框架的拓展,目前它仅支持EasyMock和Mockito。

PowerMock能用于Android单元测试吗?

有经验的童鞋可能已经想到了,PowerMock之所以能够这么强大是因为它使用自定义的类加载器,并且在运行时操作字节码,所以他是根植于虚拟机环境的,而Java的虚拟机跟Android的虚拟机是不一样的,那么PowerMock能在Android的Dalvik虚拟机上执行嘛?

答案是否定的,PowerMock当前并没有提供适用于Dalvik虚拟机的类加载器,所以PowerMock在Android环境中是跑不起来的(有牛叉的童鞋可以考虑帮PowerMock实现下,记得分享~)

但是,考虑到单元测试的特点,我们并不是一定要被测程序在设备上运行起来,我们需要的是对所有功能单元进行逻辑覆盖,那么基于这一点,如果Java虚拟机与Dalvik差别不大的话,我们是不是可以在Java虚拟机上进行Android项目的单元测试呢?正是基于这点出发,Google非Android项目的童鞋想到了下面的Work Around方式。

创建Android Junit单元测试工程

假设我们有一个标准的Android项目,我们该如何创建我们的测试工程呢?

1. 不同于传统的Android测试项目创建,第一步我们得创建个标准的Java工程:

2. 选择我们刚创建的Java项目,右键选择属性,然后在Java Build Path项选择Projects标签,点击Add键,把被测Android项目加进来。

3. 下载PowerMock的工具包,这里我选择是最新的PowerMock+Mockito集合,然后全部解压到本地。

4. 然后我们要把PowerMock的工具包加到我们的项目里。同样是右键项目,选择属性到Java Build Path, 然后选择Libraries标签,使用Add External JARs功能把刚解压的所有Jar包加到项目   里。

5. 接上一步我们要把Android.jar包也加到我们的项目里,不然我们的Android项目就会编译失败。这里要注意,在我们配置Android开发环境时,我们会通过Android SDK Manager下载相应的Android版本到本地,通常这个Jar包在sdk\platforms\android-{SDK version}下,我们可以选择这个Jar包来配置我们的项目,但是有个潜在的问题就是以后当我们测试的代码用到Android包里的API时,就会直接抛一个RuntimeException:Stub!异常,这是因为原生的Android Jar包里的API是没有具体实现的,只是各种类和方法的签名,而内容就是直接抛这个RuntimeException异常,并且即使我们想Mock住这些方法也是不行的,所以最好不要用这个Jar包。那解决办法就是下载Android源码,删除这些异常,然后重新编译成Jar包供使用。在Google的文章里提供了一个Android包,但是比较旧,有可能没法用。这里有个稍微新点的,但是不知道其版本号(http://www.4shar(_)ed.com/get/KWwSl5an/android.html)(把(_)去掉)。

6. 这一步尤其重要,我们得把这几个Jar包排好序,不然可能编译不通过。同样在Java Build Path里选择Order and Export,把这些Jar包按下面的顺序排部:

至此,使用PowerMock的Android Junit环境我们就配置好了,接下来就可以写单元测试了~

参考资料

PowerMock on Android (Google Solution)

Mocking Android System Objects using PowerMock

如果您看了本篇博客,觉得对您有所收获,请点击下面的 [推荐]

如果您想转载本博客,请注明出处

如果您对本文有意见或者建议,欢迎留言

单元测试不是梦,Android+PowerMock系列(1) —— 在Eclipse里搭建测试环境的更多相关文章

  1. 简单谈谈eclipse下搭建PhoneGap环境来开发Android程序 - linux86(转)

    原来在逛园子的时候一不小心发现了一个新概念“PhoneGap”简称PG,我一直都喜欢追逐新事物,自然就产生了好奇心.于是乎我就在百度上面Google了一下PhoneGap是什么东西.简单的说就是用另一 ...

  2. Android studio 搭建测试环境 创建虚拟机

    1.打开android studio2.0 ,选择AVD Manger 2.选择Create Virtual Device 3.在左侧Category中选择Phone,然后选择自己喜欢的手机型号,点击 ...

  3. java-cef系列视频第二集:搭建开发环境

    上一集我们介绍了如何从官方代码编译java-cef. 本视频介绍了如何使用eclipse搭建java-cef二次开发环境. 下一集我们将给java-cef添加flash支持. 本作品采用知识共享署名- ...

  4. 流程引擎Activiti系列:在eclipse中搭建咖啡兔的Activiti演示工程中的各种坑及其解决方法(kft-activiti-demo-no-maven)

    近期在学习activiti,打算基于现有的框架,比如activiti-explorer或者咖啡兔的示例工程 kft-activiti-demo,在此基础上添加自己的业务流程,看看是否可以走通,以及这个 ...

  5. Android配置时,点击eclipse里Window->Preferences里的android选项出错

    An error has occurred when creating this preference page. 解决方法:重起eclipse

  6. Android开发系列之搭建开发环境

    接触Android好久了,记得09年刚在中国大陆有点苗头的时候,我就知道了google有个Android,它是智能机操作系统.后来在Android出1.5版本之后,我第一时间下载了eclipse开发工 ...

  7. Android拓展系列(11)--打造Windows下便携的Android源码阅读环境

    因为EXT和NTFS格式的差异,我一直对于windows下阅读Android源码感到不满. 前几天,想把最新的android5.0的源码下下来研究一下,而平时日常使用的又是windows环境,于是专门 ...

  8. Android学习系列(37)--App调试内存泄露之Context篇(下)

    接着<Android学习系列(36)--App调试内存泄露之Context篇(上)>继续分析. 5. AsyncTask对象 我N年前去盛大面过一次试,当时面试官极力推荐我使用AsyncT ...

  9. [转]Android Studio系列教程六--Gradle多渠道打包

    转自:http://www.stormzhang.com/devtools/2015/01/15/android-studio-tutorial6/ Android Studio系列教程六--Grad ...

随机推荐

  1. thread.wait的一个好例子

    int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); HelloThread thread; thread.star ...

  2. VS2012的安装项目只能用InstallShield Limited Edition[附资源下载]

    以前版本的Visual Stuido中安装项目都可以使用微软自家的Visual Studio Installer,但是到了VS2012这一切都变了,只能用InstallShield Limited E ...

  3. hdu2128之BFS

    Tempter of the Bone II Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 98304/32768 K (Java/ ...

  4. android十六进制颜色代码转换为int类型数值

    android开发中将十六进制颜色代码转换为int类型数值方法:Color.parseColor("#00CCFF")返回int数值;

  5. JAVA获取随机数

    在Java中我们能够使用java.util.Random类来产生一个随机数发生器.它有两种形式的构造函数,各自是Random()和Random(long seed).Random()使用当前时间即Sy ...

  6. Qt 学习之路:输入元素

    前面的章节中,我们看到了作为输入元素的MouseArea,用于接收鼠标的输入.下面,我们再来介绍关于键盘输入的两个元素:TextInput和TextEdit. TextInput是单行的文本输入框,支 ...

  7. 使用DBOutputFormat把MapReduce产生的结果集导入到mysql中

    数据在HDFS和关系型数据库之间的迁移,主要有以下两种方式 1.按照数据库要求的文件格式生成文件,然后由数据库提供的导入工具进行导入 2.采用JDBC的方式进行导入 MapReduce默认提供了DBI ...

  8. iOS-你真的会用UIMenuController吗?(详细)

    UIMenuController的介绍 什么是UIMenuController? UIMenuController是UIKit里面的控件 UIMenuController的作用在开发中弹出的菜单栏 后 ...

  9. 在eclipse中将java导出为可执行文件.

    Ref: http://java.chinaitlab.com/Eclipse/812775.html and http://www.javavids.com/video/how-to-create- ...

  10. How to Make LastPass Even More Secure with Google Authenticator

    Google Authenticator LastPass supports Google Authenticator, which is officially available as an app ...