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