Having unit test which tests the data fetch result. But after switch to use coroutines, the unit test failure is not shown as before anymore.
In app's DataRequest.kt which will fetch the data list and post to liveData, it is done inside the coroutine's launch{}:
There is exceptionHandler for the coroutineScope:
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
Log.e(TAG, "!!! exception in coroutineExceptionHandler($exception)")
exception.printStackTrace()
......
}
And used in the launching the root coroutines job:
@Throws(Exception::class)
private fun launchCoroutine(block: suspend CoroutineScope.() -> Unit): Job = serviceScope.launch(context = coroutineExceptionHandler, block = block)
The coroutines job start from calling:
launchCoroutine {
doDataFetch()
}
doDataFetch() will fetch the data and when the data list is ready in the callback it calls the onDataFetchedReady() which does the post to the liveData in the postDataList(list)
suspend fun onDataFetchedReady() = withContext(Dispatchers.IO) {
...
launch {
postDataList(list)
}
}
And in the unit test its liveData observer will get the liveData update and calling into the test function verifyExpectedDataSize() where it may detect failure:
ListRequesterTest.kt
@RunWith(AndroidJUnit4::class)
fun verifyExpectedDataSize(
originalList: List<Data>,
resultList: List<Data>
): Int {
... ...
assertTrue("the data size is wrong", (dataSize > 0 && resultList.size >= dataSize))
... ...
}
In logCat it shows:
E/DataRequest: !!! exception in coroutineExceptionHandler(java.lang.AssertionError: the data size is wrong)
Suppressed: java.lang.AssertionError: the data size is wrong
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.assertTrue(Assert.java:41)
at com.xxx.ListRequesterTest$verifyExpectedDataSize(ListRequesterTest:200)
at com.xxx.ListRequesterTest$LiveDataObserver.onChanged(ListRequesterTest.kt:64)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:131)
at androidx.lifecycle.LiveData.setValue(LiveData.java:289)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
at androidx.lifecycle.LiveData$1.run(LiveData.java:91)
at androidx.arch.core.executor.testing.InstantTaskExecutorRule$1.postToMainThread(InstantTaskExecutorRule.java:43)
at androidx.arch.core.executor.ArchTaskExecutor.postToMainThread(ArchTaskExecutor.java:101)
at androidx.lifecycle.LiveData.postValue(LiveData.java:273)
at androidx.lifecycle.MutableLiveData.postValue(MutableLiveData.java:28)
at com.yyy.DataRequest.postDataList(DataRequest.kt:200)
at com.yyy.DataRequest.access$postDataList(DataRequest.kt:39)
at com.yyy.DataRequest$onDataReady$2$invokeSuspend$$inlined$synchronized$lambda$3.invokeSuspend(DataRequest.kt:508)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
In the test in IDE it shows the green check and no error with "Tests ran to completion".
But in logCat it shows the test has failed
Suppressed: java.lang.AssertionError: the data size is wrong
How to prevent the coroutines exception handler from swallowing the test failure?