mockito - android,如何使用 mockito 测试 Runable 的运行功能
问题描述
让一个类NotifyTaskRunner
在一个线程中运行一个任务,当任务完成时,它将使用 Handler 发布一个 Runnable,在其中它将调用DataPrepareCallback::onComplete(T)
Handler 所在的任何线程。
class NotifyTaskRunner {
final private Handler handler; //new Handler(Looper.getMainLooper());
interface DataPrepareCallback<R> {
void onComplete(R result);
}
NotifyTaskRunner(@Nullable Handler handler) {
this.handler = handler;
}
<R> void asyncRun(Executor executor, final Callable<R> callable, final DataPrepareCallback<R> callback) {
final Handler theHandler = this.handler;
executor.execute(new Runnable() {
@Override
public void run() {
R result = null;
try {
result = callable.call();
} catch (Exception e) {}
if (theHandler != null) {
final R finalResult = result;
System.out.println("+++ before handler.post, result:"+result+", theHandler:"+theHandler);
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("+++ in handler.post.run(), thread: "+Thread.currentThread().getId()+", call callback.onComplete(finalResult), ret:" + finalResult);
callback.onComplete(finalResult); //<=== never get called ???
}
});
} else {
System.out.println("+++ no handler, thread: "+Thread.currentThread().getId(), ret:" + result);
callback.onComplete(result);
}
}
});
}
}
问题出在测试中,当 Handler 为 时Handler(Looper.getMainLooper())
,Runnable::run()
从未调用过,也没有DataPrepareCallback::onComplete()
.
当不通过测试时,被调用Handler
的测试工作正常。DataPrepareCallback::onComplete()
@Test
public void test_Handler() throws Exception {
ExecutorService executorPool = Executors.newFixedThreadPool(2);
final long currThreadId = Thread.currentThread().getId();
final long[] taskThreadId2 = {-1};
final CountDownLatch latch2 = new CountDownLatch(1);
Handler looper = new Handler(Looper.getMainLooper());
Callable<Bitmap> task = new Callable<Bitmap>(){
@Override
public Bitmap call() throws Exception {
return null;
}
};
NotifyTaskRunner taskRunner2 = new NotifyTaskRunner(looper);
taskRunner2.asyncRun(executorPool, task,
new DataPrepareCallback<Bitmap>() {
@Override
public void onComplete(Bitmap bmp) {
latch2.countDown();
taskThreadId2[0] = Thread.currentThread().getId();
System.out.println("+++ 222 asyncFetch.onComplete(bmp), taskThreadId2[0]:"+taskThreadId2[0]);
}
}
);
// shadowOf(getMainLooper()).idle();
// ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); //,=== these two do not help
boolean b = latch2.await(10, TimeUnit.SECONDS);
System.out.println("+++ latch2 count == 0 :"+b+", taskThreadId2[0]:"+taskThreadId2[0]);
}
打印出来的有:
......
+++ before handler.post, result:null, theHandler:Handler (android.os.Handler) {282854d8}
+++ latch2 count == 0 :false, taskThreadId2[0]:-1
如何测试Runnable'run(),验证它是否在Handler的线程上等等?
解决方案
推荐阅读
- asp.net - 通过 Windows 身份验证在两台服务器之间建立数据库连接字符串
- javascript - 请帮我处理这个旋转木马
- python - Pandas 多列交叉点忽略 na 值
- ajax - 如何根据条件执行(或不执行)ajax 调用
- php - JSON 是什么类型的,如何用 php 解析它?
- javascript - 反应:传入我的onClick函数时无法读取未定义的属性
- ios - 将 12 个 ARFrame 添加到 Array (iOS/Swift) 后 ARSCNView 冻结
- javascript - 注册组件vue js
- java - 如何在 slf4j 中格式化异常?
- webpack - 如何更改 vue.js 应用程序中的 lint 目录?