首页 > 解决方案 > 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的线程上等等?

标签: mockitorunnableandroid-handlerandroid-unit-testing

解决方案


推荐阅读