1

我正在尝试为我们正在集成Bolts的 Android 应用程序编写一些测试。

被测对象通过创建一个任务并在后台执行它来工作:

Task<MyResult> currentTask;

currentTask = MyTaskFactory.getImportantTask(parameters ...);

currentTask.continueWith(new Continuation<MyResult,MyResult>() {
        @Override
        public MyResult then(Task<MyResult> task) throws Exception {
            MyResult result = task.getResult();

            if (!task.isFaulted()) {
                if (DEBUG) {
                    logger.v("got login result back: " + result.toString());
                }

                if (result.getSuccess()) {
                    callback.onMySuccess(result.getData());
                } else {
                    callback.onMyError(result.getStatusCode(), result.getError());
                }
           }

            return result;
        }
    }, Task.UI_THREAD_EXECUTOR);

MyTaskFactory.getImportantTask() 返回一个Task,我的被测对象得到这个任务并在后台执行。当它完成时,完成应该被执行。

我已经验证在实际应用程序中,此代码工作正常。我的问题出现了,因为我试图在 Robolectric/Mockito 下运行它。

这是正在测试的代码:

myobject.runTaskWithContinuation(parameters...);

ShadowLog.d(TAG, "Waiting....");

Task<AuthenticationResult> task = controller.getCurrentTask();

assert(task != null);

ShadowApplication.runBackgroundTasks();
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();

ShadowLog.d(TAG, "Finished!");

使用此代码,并通过模拟和检测 Task 和 Continuation 进行的调用,我已经验证了 Task 正在执行并生成结果,但从未调用过 Continuation。如果我等待任务完成,我的单元测试将永远不会完成。

我确定我在这里做错了什么,但我真的不知道是什么。如何确保在测试中调用 Continuation?

4

2 回答 2

2

在您的单元测试中,由于您可以直接访问任务,请调用

task.waitForCompletion()

例如:

@Test
public void directTaskAccess() throws InterruptedException {
    Task<Boolean> task = doWorkTask();
    task.waitForCompletion();
    assertTrue(task.getResult());
}

public Task<Boolean> doWorkTask() {
    return Task.callInBackground(() -> {

        // simulate doing 'hard' work
        Thread.sleep(1000);
        return true;
    });
}

对于无法访问任务参考的其他测试,您可能需要做一些额外的工作。

这篇博文详细介绍了它:单元测试异步螺栓任务

于 2016-06-09T16:04:08.007 回答
1

使用 aCountDownLatch使测试线程等待直到达到您的继续

这是在我的 Robolectric 测试上运行的示例代码:

@Test
public void test1() throws Throwable {
    success = false;
    final CountDownLatch signal = new CountDownLatch(1);
    task.onSuccess(new Continuation<Object, Object>() {
        @Override
        public Object then(Task<Object> task) throws Exception {
            if (condition == true) {
                success = true;
            }
            signal.countDown();
            return null;
        }
    });
    signal.await(30, TimeUnit.SECONDS);
    assertTrue(success);
}
于 2015-08-28T13:51:16.967 回答