(Kotlin 1.5.21, kotlinx-coroutines-test 1.5.0)
Please consider the following code inside a androidx.lifecycle.ViewModel
:
fun mayThrow(){
val handler = CoroutineExceptionHandler { _, t -> throw t }
vmScope.launch(dispatchers.IO + handler) {
val foo = bar() ?: throw IllegalStateException("oops")
withContext(dispatchers.Main) {
_someLiveData.value = foo
}
}
}
vmScope
corresponds to viewModelScope
, in tests it is replaced by a TestCoroutineScope
. The dispatchers.IO
is a proxy to Dispatchers.IO
, in tests it is a TestCoroutineDispatcher
. In this case, the app's behavior is undefined if bar()
returns null, so I want it to crash if that's the case. Now I'm trying to (JUnit4) test this code:
@Test(expected = IllegalStateException::class)
fun `should crash if something goes wrong with bar`() {
tested.mayThrow()
}
The test fails because of the very same exception it is supposed to test for:
Exception in thread "Test worker @coroutine#1" java.lang.IllegalStateException: oops
// stack trace
Expected exception: java.lang.IllegalStateException
java.lang.AssertionError: Expected exception: java.lang.IllegalStateException
// stack trace
I have the feeling I'm missing something quite obvious here... Question: is the code in my ViewModel the right way to throw an exception from a coroutine and if yes, how can I unit test it?