Test methods of Room DAO with Kotlin Coroutines and Flow

Turns out that I wasn't properly handle Flow collection and cancelation and that was probably the cause of problem. Below is the code that works. More complex example can be found here.

@RunWith(AndroidJUnit4::class)
class CoresDaoTest {

    private lateinit var database: SpaceDatabase
    private lateinit var coresDao: CoresDao

    private val testDispatcher = TestCoroutineDispatcher()

    private val testCoresList = listOf(core2, core3, core1)

    @get:Rule
    var instantTaskExecutorRule = InstantTaskExecutorRule()

    @Before
    fun setup() {
        Dispatchers.setMain(testDispatcher)

        val context = InstrumentationRegistry.getInstrumentation().targetContext
        database = Room
            .inMemoryDatabaseBuilder(context, SpaceDatabase::class.java)
            .setTransactionExecutor(Executors.newSingleThreadExecutor())
            .build()
        coresDao = database.coresDao()
    }

    @After
    fun cleanup() {
        database.close()

        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }

    @Test
    fun testInsertAndGetAllCores() = runBlocking {
        coresDao.insertCores(testCoresList)

        val latch = CountDownLatch(1)
        val job = launch(Dispatchers.IO) {
            coresDao.getAllCores().collect { cores ->
                assertThat(cores.size, equalTo(testCoresList.size))
                latch.countDown()
            }
        }

        latch.await()
        job.cancel()
    }

Since you are using the TestCoroutineDispatcher already, using runBlockingTest won't do anything in your example.. You will have to cancel the Flow after collection or the scope in which you launched the Flow

edit: an example for such a rule can be found here


To test Flow, the best APIs I found are .take(n).toList(). You can use runBlockingTest and you shouldn't need to use withContext to move the execution to another thread.

You can find an example of how it works here: https://github.com/manuelvicnt/MathCoroutinesFlow/blob/master/app/src/test/java/com/manuelvicnt/coroutinesflow/fibonacci/impl/NeverEndingFibonacciProducerTest.kt#L38