Robolectric无法在后台线程上调用setValue

时间:2019-10-31 16:15:52

标签: android android-asynctask robolectric android-livedata androidx-test

我正在测试AsyncTask调用onPostExecute实例的setValue的{​​{1}}。由于我是从LiveData调用setValue的,因此不会出现与UI线程进行的调用有关的问题。

但是我在Robolectric单元测试中运行了此命令:onPostExecute

要使此单元测试等待后台和前台任务完成,我可以通过以下方式利用等待性工具:

java.lang.IllegalStateException: Cannot invoke setValue on a background thread

这在var cf = new CompletableFuture<T>(); livedata.observe(ctrl.get(), it -> cf.complete(it)); // ... perform the AsyncTask that will update livedata in onPostExecute await().until(() -> { flushBackgroundThreadScheduler() flushForegroundThreadScheduler() cf.isDone }); 通话中抛出了IllegalStateException: Cannot invoke setValue on a background thread !!!!

为什么我会收到此异常?以及如何像在UI线程中一样执行flushForegroundThreadScheduler()

更新

记录线程似乎onPostExecuteflushBackgroundThreadScheduler()都是内联同步执行的。我可以观察到:

flushForegroundThreadScheduler()

由于传递给LiveData created on thread 763324286 Background thread 1519527121 LiveData updated on thread 1519527121 的lambda在另一个线程上运行,因此await.untilflushBackgroundThreadScheduler()都在该线程1519527121上执行。

因此,我可以通过在与UI线程相对应的测试线程中运行以下变通办法来解决我的问题。但是,我需要flushForegroundThreadScheduler()才能成功,但我不喜欢它。

Thread.sleep()

1 个答案:

答案 0 :(得分:0)

我们必须考虑以下因素:

  1. Robolectric:Learner(data, labels, ...) 是内联同步执行的。
  2. 等待性:flushForegroundThreadScheduler()在后​​台线程中评估直到条件。

从这两个语句中,我们观察到从传递到await.until(<Callable>)的{​​{1}}中调用flushForegroundThreadScheduler()会导致在后台线程中调度预定的前台任务,从而回答了第一个OP问题: 为什么我会收到此异常?

回答第二个OP问题:

  

如何像在UI线程中一样执行Callable

由于Robolectric为UI操作和测试代码共享一个线程,因此我们必须使用await.until(<Callable>)来指示应该在启动Awaitility的测试用例的同一线程上评估直到条件。 OP示例代码应固定为:

onPostExecute