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())
}