Why compose ui testing's IdlingResource is blocking the main thread?

1.1k Views Asked by At

I've written a "minimal" AS project to replicate my the problem I'm facing. Here's the gh link.

I'm trying to write an end-to-end ui test in my compose-only project. The test covers a simple sign-in -> sync data -> go to main view use case.

Here's the whole test:

@HiltAndroidTest
class ExampleInstrumentedTest {

    @get:Rule(order = 1)
    val hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 2)
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Inject
    lateinit var dao: DummyDao

    val isSyncing = mutableStateOf(false)

    @Before
    fun setup() {
        runBlocking {
            hiltRule.inject()
            dao.deleteAllData()
            dao.deleteUser()
        }

        composeTestRule.activity.isSyncingCallback = {
            synchronized(isSyncing) {
                isSyncing.value = it
            }
        }

        composeTestRule.registerIdlingResource(
            object : IdlingResource {
                override val isIdleNow: Boolean
                    get() {
                        synchronized(isSyncing) {
                            return !isSyncing.value
                        }
                    }
            }
        )
    }

    @Test
    fun runsTheStuffAndItWorks() {
        composeTestRule
            .onNodeWithText("login", ignoreCase = true, useUnmergedTree = true)
            .assertIsDisplayed()
            .performClick()

        composeTestRule
            .onNodeWithTag("sync")
            .assertExists()

        composeTestRule.waitForIdle()

        assertFalse(isSyncing.value)

        composeTestRule.onRoot().printToLog("not in the list")

        composeTestRule
            .onNodeWithTag("the list", useUnmergedTree = true)
            .assertIsDisplayed()
    }
}

The test runs "alright" up to the point where it should be waiting for the sync worker to finish its job and finally navigate to the "main composable".

Unfortunately, the test seems to be blocking the device's ui thread when the idling resource is not idle, finishing the test immediately as the idling resource does become idle.

I've tried using Espresso's IdlingResource directly, which also didn't work, showing similar results. I've tried adding compose's IdlingResource in different points as well, but that also didn't work (adding one between navigation calls also blocks the UI thread and the test fails even sooner).

What am I doing wrong here? Am I forgetting to setup something?

0

There are 0 best solutions below