同步测试线程、UI线程和CursorLoader线程
Posted
技术标签:
【中文标题】同步测试线程、UI线程和CursorLoader线程【英文标题】:Synchronize testing thread, UI thread, and CursorLoader thread 【发布时间】:2015-08-29 19:29:04 【问题描述】:我的理解是,android 插桩 JUnit 测试在它们自己的线程上运行,除非使用 @UiThread
注释或调用 Instrumentation.runOnMainSync()
或 Activity.runOnUiThread()
。现在我正在尝试使用CursorLoader
来访问我的应用程序的数据库并填充ListView
。我还有一个测试可以验证 ListView
是否正确填充。
我的问题是我需要同步三个线程:测试线程应该等到CursorLoader
线程完成并通知UI 线程填充ListView
。为了创建CursorLoader
,我在LoaderManager
支持下注册了LoaderCallbacks
,并在onCreateLoader()
中创建实例。然后onLoadFinished()
改变ListView
的适配器的光标。
现在我需要确保我的测试等到onLoadFinish()
被调用后,才能尝试访问ListView
的子视图。我目前的想法是在测试可以调用的LoaderCallbacks
实现中添加一个waitForData()
方法。但是,我不确定如何实现此方法。我可以简单地使用wait()
,然后在onLoadFinished()
中使用notifyAll()
吗?还是我需要使用更复杂的东西,比如Semaphore
?
【问题讨论】:
【参考方案1】:您在如何做这件事上走在正确的轨道上。一般的方法确实只是阻塞主测试线程,直到工作线程完成。这是一个使用ConcurrentUnit的示例:
final Waiter waiter = new Waiter();
LoaderManager.LoaderCallbacks callbacks = new LoaderManager.LoaderCallbacks()
public void onLoadFinished(Loader<D> loader, D data)
waiter.assertEquals(someValue, "foo");
waiter.resume();
//...
;
// register callbacks...
waiter.await(5000); // wait 5 seconds for resume
【讨论】:
感谢您回答我的问题。对不起,我没有早点回复。我有一个问题:SessionStatus
是什么?
@Code-Apprentice 如果我记得的话,这只是 android API 的一部分。唯一与测试相关的位是使用Waiter
,它允许您的测试等到您准备好恢复,这可能是在收到一些回调之后。
谷歌搜索“android SessionStatus”不会对 Android API 文档产生影响,因此我得出结论,这是特定于该示例来自何处的自定义类。我也不确定如何将它融入我现有的应用程序和测试框架。 SessionListener
是否与应用程序代码本身或测试一起使用? Waiter
在哪里声明?我在哪里打电话waiter.await()
?你能提供一个更完整的例子吗?
@Code-Apprentice 我不记得这个例子是从哪里来的,但是因为它会分散注意力,所以这里有一个更新的例子。它未经测试,但基本要点仍然存在。在您的单元测试中,创建一个 Waiter。调用 Waiter.await 来阻止测试。然后,当您准备好取消阻止测试时,从您的回调中调用 Waiter.resume。这是适用于测试任何异步代码的基本模式,无论 API 是什么样的。
感谢您最新评论中的回答和描述。有机会我会去看看。【参考方案2】:
Espresso 处理这种类型的同步。我还没有使用它来弄清楚细节,但它看起来很有希望。
【讨论】:
以上是关于同步测试线程、UI线程和CursorLoader线程的主要内容,如果未能解决你的问题,请参考以下文章
使用 CursorLoader 查询 SQLite DB 并填充 AutoCompleteTextView