背景
参考了网上诸多的Android异步单元测试的方法之后,发现方法就两种,但是却没有发现这两种方法的一些关键说明,也正是少了这些关键说明,我绕了很大的圈子
方法一
public class ExampleInstrumentationTeseCase extends InstrumentationTestCase {
private Activity mActivity;
private Context mApplicationContext;
@Override
protected void setUp() throws Exception {
super.setUp();
Intent intent = new Intent();
intent.setClassName("com.example.demo", TestcaseActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity = (TestcaseActivity) getInstrumentation().startActivitySync(intent);
mApplicationContext = mActivity.getApplicationContext();
}
@Override
protected void tearDown() throws Exception {
mActivity.finish();
try {
super.tearDown();
} catch (Exception e) {
e.printStackTrace();
}
super.tearDown();
}
public void testAsyncTask() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
// 在UI线程中执行异步操作
runTestOnUiThread(new Runnable() {
@Override
public void run() {
// 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
new MyAsyncTask() {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
assertEquals("kale", result);
signal.countDown();
}
}.execute();
}
});
signal.await();
}
}
方法二
public void testAsyncTask() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
final String TDD = "TDD";
// 在UI线程中执行异步操作
runTestOnUiThread(new Runnable() {
@Override
public void run() {
// 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
new MyAsyncTask() {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
assertEquals("kale", result);
synchronized (TDD) {
TDD.notify();
}
}
}.execute();
}
});
synchronized (TDD) {
TDD.notify();
}
}
分析&&关键点
上面两种实现方法其实很类似的,就是借助同步工具来进行阻塞辅助,而且网上很多地方都有这种代码,但是,实际上跑起来之后,发现是一直没有跑完的。
针对方法一来进行
分析:当执行assertEquals的时候,测试代码就结束了,也不会执行signal.countDown(),因此程序一直阻塞,导致没有跑完
于是,将signal.countDown();
和 assertEquals("kale", result);
交换位置
public void testAsyncTask() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
// 在UI线程中执行异步操作
runTestOnUiThread(new Runnable() {
@Override
public void run() {
// 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
new MyAsyncTask() {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
signal.countDown();
assertEquals("kale", result);
}
}.execute();
}
});
signal.await();
// mark1
}
发现可以跑完了,但是无论如何都是测试通过的,即便值是不一样。
分析:当执行signal.countDown();
之后,代码就会跳转到上面注释的mark1的位置继续执行,而不是执行assertEquals("kale", result);
,因此无论断言的值是什么都会成功的,因为根本没有执行到断言那里
于是,再次修改代码,将回调中的值,用全局的私有变量缓存起来,然后在signal.await();
方法后面才进行断言判断,于是得出
最终可行的代码
private String temp = null;
public void testAsyncTask() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
// 在UI线程中执行异步操作
runTestOnUiThread(new Runnable() {
@Override
public void run() {
// 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
new MyAsyncTask() {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
temp = result;
signal.countDown();
}
}.execute();
}
});
signal.await();
assertEquals("kale", temp);
}
亲测可行~~,但是就是写起来有点怪异,因为一个测试方法用到全局全局变量来缓存