https://kotlinlang.org logo
#coroutines
Title
# coroutines
e

Erik

02/11/2020, 3:54 PM
I'm having issues testing expected exceptions in coroutines on Android. Full MWE in the attached code snippet. As far as I understand is that when a new coroutine is launched from a unit test, even if that indirectly happens on the
TestCoroutineDispatcher
or
TestCoroutineScope
, then any exceptions are swallowed (although the stack traces are printed). What is the general pattern to work with expected exceptions in unit tests and coroutines on Android?
a

Andrew

02/12/2020, 2:41 AM
I think if you wanted to test an expected exception you would use a suspend function and call that in the test. The launchSomething() you have is similar to what would be an event handler function which you would not be waiting for a result from and therefore not care what exception it throws.
I am also not sure if Dispatchers.Main is really replaced by the test scope, its called from the test scope then the new scope becomes Dispatchers.Main when the exception is thrown.
e

Erik

02/12/2020, 8:33 AM
That does make sense. Thanks!
I am sure that
Dispatchers.Main
is replaced in the tests dispatcher. I have verified this by simply
printlnI(Dispatchers.Main)
, which prints some
TestMainDispatcher@2812cbfa
instance.
What is interesting, though, is that if I run that view model function that launches a crashing coroutine on the view model scope, then the app crashes. That's something I might want to verify.
But as expected: I cannot catch that exception anywhere but in the launched coroutine. As per the docs (of course): https://kotlinlang.org/docs/reference/coroutines/exception-handling.html#exception-propagation
a

Andrew

02/12/2020, 4:46 PM
I was learning some of this as I was trying to answer the question. It seems exceptions inside a coroutine are similar to ones that happen inside a 2nd thread, even if the coroutine is running on the same/main thread.
Also it looks like if you want normal exception handling you would use await
e

Erik

02/12/2020, 7:33 PM
I've chosen not to throw an exception, as it's a fire and forget (
launch
) coroutine. So my coroutine will now handle the exception by propagating that information through other mechanisms unrelated to coroutines and exceptions.
8 Views