大部分内容也适合Java,此处主要是对sdk类别的module做unit test,不涉及UI
1. 配置
1) 对于涉及到android原生的类库返回默认的对象,否则,之后遇到Log之类的语句都需要手动mock,但是不要期待这个配置对android API提供全面的支持
testOptions { unitTests.returnDefaultValues = true }
参考这边的说明 Unit testing support
"Method ... not mocked."
The android.jar file that is used to run unit tests does not contain any actual code - that is provided by the Android system image on real devices. Instead, all methods throw exceptions (by default). This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked e.g. using Mockito). If that proves problematic, you can add the snippet below to your build.gradle to change this behavior:
android {
// ...
testOptions {
unitTests.returnDefaultValues = true
}
}
2) 配置依赖库
testCompile 'junit:junit:4.12' testCompile "org.mockito:mockito-core:1.10.+" testCompile ('org.powermock:powermock-api-mockito:1.6.3') { exclude module: 'hamcrest-core' exclude module: 'objenesis' } testCompile ('org.powermock:powermock-module-junit4:1.6.3') { exclude module: 'hamcrest-core' exclude module: 'objenesis' }
其中powermock用于对static和final方法提供mock支持
另外也有人对powermock提出了质疑,大致的理由是,为了实现对static和final方法的mock,powermock在jvm中对被测试类的字节码进行了部分修改(只是在测试运行时进行了修改,并不会影响你的源码),所以实际测试的类和你自己写的是有部分区别的,而且,进一步就引发了对static用法的质疑,参见:
PowerMock + Mockito VS Mockito alone
Why is wide usage of PowerMock problematic
3) 设置Android Studio
左边栏Build Variants -> Test Artifact 选择 Unit Tests
2. 对于单进程的异步请求单元测试
首先有如下的类
public class JustAClass { //callback接口 public interface JustACallBack { void callFunc(JustAResult result); } //callback中携带的数据父接口 public interface JustAResult {} //用于测试的数据类 public class ImplementedResult implements JustAResult{ public ImplementedResult(String content) {this.content = content;} public String content; } //此处的测试函数 public void mainThreadFunc(final JustACallBack callBack) { callBack.callFunc(new ImplementedResult("can you reach me")); } }
Mockito提供了ArgumentCaptor用于获取异步回调的结果
public class JustAClassTest { @Captor ArgumentCaptor<JustAClass.JustAResult> captor; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } @Test public void testMainThreadFunc() throws Exception { JustAClass justAClass = new JustAClass(); JustAClass.JustACallBack callBack = Mockito.mock(JustAClass.JustACallBack.class); justAClass.mainThreadFunc(callBack); Mockito.verify(callBack).callFunc(captor.capture()); Assert.assertEquals(((JustAClass.ImplementedResult) captor.getValue()).content, "can you reach me"); } }
3. 如果被测试函数启动了一个子线程,然后在子线程中调用回调接口,那么上面的测试是无效的
一般mockito会报错 Wanted but not invoked,出错点在
Mockito.verify(callBack).callFunc(captor.capture());
原因是子线程尚未结束,而主进程已经开始去校验结果了。
首先被测试的类
public class JustAClass { //callback接口 public interface JustACallBack { void callFunc(JustAResult result); } //callback中携带的数据父接口 public interface JustAResult {} //用于测试的数据类 public class ImplementedResult implements JustAResult{ public ImplementedResult(String content) {this.content = content;} public String content; } //此处的测试函数 public void mainThreadFunc(final JustACallBack callBack) { callBack.callFunc(new ImplementedResult("can you reach me")); } //此处的测试函数 public void subThreadFunc(final JustACallBack callBack) { new Thread(new Runnable() { @Override public void run() { //模拟耗时操作0.5s try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } callBack.callFunc(new ImplementedResult("can you reach me")); } }).start(); } }
此时可以通过加锁的方式来等待子线程结束,这边用的CountDownLatch
A CountDownLatch
is initialized with a given count. The await
methods block until the current count reaches zero due to invocations of the countDown()
method, after which all waiting threads are released and any subsequent invocations of await
return immediately. This is a one-shot phenomenon -- the count cannot be reset.
public class JustAClassTest { @Captor ArgumentCaptor<JustAClass.JustAResult> captor; CountDownLatch latch; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); //for child thread async latch = new CountDownLatch(1); } @Test public void testMainThreadFunc() throws Exception { JustAClass justAClass = new JustAClass(); JustAClass.JustACallBack callBack = Mockito.mock(JustAClass.JustACallBack.class); justAClass.mainThreadFunc(callBack); Mockito.verify(callBack).callFunc(captor.capture()); Assert.assertEquals(((JustAClass.ImplementedResult) captor.getValue()).content, "can you reach me"); } @Test public void testSubThreadFunc() throws Exception { JustAClass justAClass = new JustAClass(); justAClass.subThreadFunc(new JustAClass.JustACallBack() { @Override public void callFunc(JustAClass.JustAResult result) { Assert.assertTrue(result instanceof JustAClass.ImplementedResult); JustAClass.ImplementedResult resultReal = (JustAClass.ImplementedResult) result; Assert.assertEquals("can you reach me", resultReal.content); latch.countDown(); } }); //wait 1s maximum before callback returns latch.await(1000, TimeUnit.MILLISECONDS); } }
相关推荐
Android单元测试的小例子
学习Android有一段时间了,虽然前段时间对软件测试有了一些了解,不过接触android的单元测试却是头一次。这几天在物流大赛上也用了不少时间,所以对于android的单元测试没有太深入的研究,所以先写个基本入门吧!...
节省时间并在Android上清除您的单元测试!
Android单元测试,结合一些测试框架(如:Robolectric、Mockito等)与Volley网络请求的单元测试
Android Studio JUnit单元测试
关于Android 单元测试的一个案例,按键点击事件测试
AndroidUT 具体说明(已完结) Android单元测试(一):JUnit框架的使用 Android单元测试(二):...Android单元测试(七):MVP与单元测试 Android单元测试(八):Dagger与单元测试 Android单元测试(九):查漏补缺篇
android不用另建工程进行单元测试及改变测试方法执行顺序示例代码
android 单元测试
Android单元测试简单Demo,教程在:http://blog.csdn.net/yanzhenjie1003/article/details/44919777
本文适用鱼产品、开发、测试、运维等人员学习使用并搭建单元测试框架,用于日常开发人员单元测试、测试人员自动化测试等
总结个人在项目开发中进行单元测试的方法 ActivityInstrumentationTestCase2 ServiceTestCase android.test.InstrumentationTestRunner 等开发日志
这是一个Android异步图片加载的例子
这是一个android的单元测试实例,包括登录等三个界面,测试代码是单独的一个项目
这是第二个android单元测试实例,测试代码和被测代码在同一个项目中,被测代码中只有一个简单的加法函数
Android JUnit单元测试基本实例
Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 (三个全) Android异步下载网络图片 ...
Android异步操作数据库
Android添加单元测试的方法与步骤 Android 添加单元测试的方法与步骤
用Junit对Android应用进行单元测试的一些方法,从网上找到的,供参考