Методы испытаний помещения DAO с сопрограммами Kotlin и Flow - PullRequest
1 голос
/ 28 октября 2019

Я пытаюсь перейти с LiveData на Flow в моей комнате Dao. Приложение работает нормально, но у меня проблемы с тестированием поведения. Когда я запускаю тест, он запускается и работает неопределенно долго. Я также пытался использовать kotlinx.coroutines.test runBlockingTest , но у меня возникла проблема с «Эта работа еще не завершена», как здесь . Может ли кто-нибудь указать мне правильное направление, как проверить поведение моего CoresDao?

@Dao
interface CoresDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertCores(cores: List<Core>)

    @Transaction
    suspend fun replaceCoresData(cores: List<Core>) {
        deleteAllCores()
        insertCores(cores)
    }

    @Query("SELECT * FROM cores_table")
    fun getAllCores(): Flow<List<Core>>

    @Query("DELETE FROM cores_table")
    suspend fun deleteAllCores()
}

@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).build()
        coresDao = database.coresDao()
    }

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

        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }

    @Test
    fun testGetAllCores(): Unit = runBlocking {
        withContext(Dispatchers.Main) {
            runBlocking { coresDao.insertCores(testCoresList) }

            val coresList = mutableListOf<Core>()
            coresDao.getAllCores().collect { cores -> coresList.addAll(cores) }

            assertThat(coresList.size, equalTo(testCoresList.size))
        }
    }
}

Ответы [ 3 ]

1 голос
/ 29 октября 2019

Чтобы протестировать Flow, я нашел лучшие API-интерфейсы .take(n).toList(). Вы можете использовать runBlockingTest, и вам не нужно использовать withContext для перемещения исполнения в другой поток.

Пример работы здесь можно найти: https://github.com/manuelvicnt/MathCoroutinesFlow/blob/master/app/src/test/java/com/manuelvicnt/coroutinesflow/fibonacci/impl/NeverEndingFibonacciProducerTest.kt#L38

1 голос
/ 28 октября 2019

Поскольку вы уже используете TestCoroutineDispatcher, использование runBlockingTest ничего не изменит в вашем примере. Вам придется cancel Flow после сбора или scope, в котором вы запустилиFlow

edit: пример для такого правила можно найти здесь

0 голосов
/ 29 октября 2019

Оказалось, что я неправильно обработал сбор и отмену потока, и это, вероятно, было причиной проблемы. Ниже приведен код, который работает. Более сложный пример можно найти здесь .

@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()
    }
...