https://kotlinlang.org logo
Title
c

czuckie

05/17/2023, 8:33 AM
I'm at my wits end, I think https://github.com/robolectric/robolectric/issues/7055#issuecomment-1482789098 is causing me issues. Is anyone capable of verifying the conclusion in that github comment? I've recently migrated a lot of tests over to robolectric and have now hit a point where I get consistent test failures. Is there anyway to drain pending dispatcher?
I found a way. Like all good solutions, it involves just a tiny bit of reflection:
private fun environmentIsSane() {
    val clazz =
        javaClass.classLoader.loadClass("androidx.compose.ui.platform.AndroidUiDispatcher")
    val combinedContextClass =
        javaClass.classLoader.loadClass("kotlin.coroutines.CombinedContext")
    val companionClazz = clazz.getDeclaredField("Companion").get(clazz)
    val combinedContext = companionClazz.javaClass.getDeclaredMethod("getMain")
        .invoke(companionClazz) as CoroutineContext

    val androidUiDispatcher = clazz.cast(
        combinedContextClass.getDeclaredField("element").apply { isAccessible = true }
            .get(combinedContext)
    )

    var scheduledFrameDispatch =
        clazz.getDeclaredField("scheduledFrameDispatch").apply { isAccessible = true }
            .getBoolean(androidUiDispatcher)
    var scheduledTrampolineDispatch =
        clazz.getDeclaredField("scheduledTrampolineDispatch").apply { isAccessible = true }
            .getBoolean(androidUiDispatcher)

    val dispatchCallback = clazz.getDeclaredField("dispatchCallback").apply { isAccessible = true }.get(androidUiDispatcher) as Runnable

    if (scheduledFrameDispatch || scheduledTrampolineDispatch) {
        dispatchCallback.run()
        scheduledFrameDispatch =
            clazz.getDeclaredField("scheduledFrameDispatch").apply { isAccessible = true }
                .getBoolean(androidUiDispatcher)
        scheduledTrampolineDispatch =
            clazz.getDeclaredField("scheduledTrampolineDispatch").apply { isAccessible = true }
                .getBoolean(androidUiDispatcher)
    }

    assertFalse(scheduledFrameDispatch)
    assertFalse(scheduledTrampolineDispatch)
}