hey folks, i have this unit test which tests my da...
# coroutines
m
hey folks, i have this unit test which tests my dao correctly observe a database through a channel
Copy code
@Test
    fun `should receive updated data when querying all challenges`() {
        val initChallenges = mutableListOf(Challenge(...),Challenge(...))

        val newSurveyChallenge = SurveyChallenge(...)

        val expectedChallenges = listOf(
            initChallenges,
            initChallenges += newSurveyChallenge
        )

        initChallenges.forEach(challengeDao::addOrUpdate)

        runBlocking {
            val channel = repository.availableChallenges(coroutineContext)

            val actualChallengesLists = async(IO) {
                channel.fold(mutableListOf<List<Challenge>>()) { list, challenges -> list.apply { add(challenges) } }
            }

            delay(300)
            challengeDao.addOrUpdate(newSurveyChallenge)
            delay(300)
            channel.cancel()

            assertThat(actualChallengesLists.await()).containsExactlyElementsIn(expectedChallenges).inOrder()
        }
without those
delay
, my test fail because the database doesnt have the time to notify anything. But having a delay looks like a code smell to me. Is there a better way to test this behavior? For the record I use
sqldelight
and
robolectric
to test that
g
Indeed it is a code smell, it implies you're not properly synchronizing on something. You need to expose the database "I'm ready to fire events" as a synchronization point. Exactly how to do that of course is the work...
Ok so I've got a very opinionated answer, I hope thats OK, my opinions (which you can choose to ignore) are to use immutable list semantics, and use a more simple value assertion. My less opinionated answer which I think its important to you is to use a couple functional combinators on the channel object, and a
withTimeoutOrNUll
to try and ensure completion. https://gist.github.com/Groostav/a5695bdbe2e4df22824d0cad7d32e8fd