英文:
runTest does not run on main thread
问题
我正在编写一个测试,并从标准库中收到以下错误信息:
java.lang.IllegalStateException: Method addObserver must be called on the main thread
这是我的简化测试方法:
@Test
fun useAppContext() = runTest {
assert(isMainThread())
}
我如何使这个测试成功?我需要在我的测试中的某个地方添加一个观察者,但因为我需要在主线程上这样做,所以测试失败。
英文:
I am writing a test and I get this error from a standard library:
java.lang.IllegalStateException: Method addObserver must be called on the main thread
This is my simplified test method:
@Test
fun useAppContext() = runTest {
assert(isMainThread())
}
How can I make this test succeed? I need to add an observer somewhere in my test which fails because I need to do so on the main thread.
答案1
得分: 3
代码部分不需要翻译,以下是翻译好的内容:
像runBlocking
一样(以及直接在@Test
方法中编写的代码一样),runTest
中的代码默认在测试线程上运行,而不是在主线程上运行。这通常是您想要的行为,因为如果不让出主线程,它将不会运行布局,您的UI将完全冻结。
在UI线程上运行测试的特定部分
如果您只有测试的特定部分应在UI线程上运行,例如您的addObserver
调用示例,您可以为测试的该部分切换协程调度器。
用withContext(Dispatchers.Main)
包围方法的相关部分
@Test
fun someTestMethod() = runTest {
withContext(Dispatchers.Main) {
assert(isMainThread())
}
}
在UI线程上运行整个测试
如果您确实希望在主线程上运行测试(例如,因为它是一个不涉及任何布局的简单测试,或者因为您想手动控制何时使用suspend
方法(例如Compose的withFrameNanos
)让出主线程),可以使用@UiThreadTest
注释来实现。
用@UiThreadTest
注释测试方法(或者如果所有@Test
、@Before
和@After
方法都应在UI线程上运行,则注释类)。
@Test
@UiThreadTest
fun someTestMethod() = runTest {
assert(isMainThread())
}
英文:
Like runBlocking
(and like code written directly in @Test
methods), code within runTest
is run on the test thread by default, rather than on the main thread. This is usually the behavior you want, because if you don't yield the main thread, it will not run layouts, and your UI will be completely frozen.
To run a specific part of your test on the UI thread
If you just have a specific part of your test that should be run on the UI thread, such as your example of the addObserver
call, you can switch the coroutine dispatcher for that specific part of the test.
Surround the relevant part of your method with withContext(Dispatchers.Main)
@Test
fun someTestMethod() = runTest {
withContext(Dispatchers.Main) {
assert(isMainThread())
}
}
To run your entire test on the UI thread
If you do want to run your test on the main thread (for example, because it's a simple test that doesn't involve any layouts, or because you want to manually control when you yield the main thread with suspend
methods (such as Compose's withFrameNanos
), this can be done with the @UiThreadTest
annotation.
Annotate the test method (or the class, if all @Test
, @Before
, and @After
methods should be run on the UI thread) with @UiThreadTest
.
@Test
@UiThreadTest
fun someTestMethod() = runTest {
assert(isMainThread())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论