Как макетировать комнату Android с помощью метода транзакций с помощью Mockk - PullRequest
0 голосов
/ 07 июня 2019

Я пытаюсь сделать несколько юнит-тестов для моей бизнес-логики. У меня есть хранилище, в котором я сохраняю в базу данных комнаты (2.1.0-rc01) некоторые данные из ответа. Сохранение данных в разных таблицах с разным дао в одной транзакции. Код упрощен:

ItemRepository

suspend fun saveItems(response: Response) {
    val items = response.items.map { it.toLocalItem() }
    val subItems = response.items.flatMap { item ->
            item.subItems.map { it.toLocal(item.id) }
        }

    db.withTransaction {
        db.itemDao().deleteAll()
        db.itemDao().insertAll(items)
        db.subItemDao().insertAll(subItems)
    }
}

Для юнит-теста я использую библиотеку Mockk. Как я могу смоделировать комнату с методом транзакции? withTransaction объявляется как

suspend fun <R> RoomDatabase.withTransaction(block: suspend () -> R): R

Я пытаюсь написать тест

@MockK
private lateinit var database: AppDatabase
@MockK
private lateinit var itemDao: ItemDao
@MockK
private lateinit var subItemDao: SubItemDao


@Test
fun checkSaveItems() = runBlocking {
    repository = ItemRepository(database)
    coEvery { database.itemDao() } returns itemDao
    coEvery { database.subItemDao() } returns subItemDao

    //TODO: execute database.withTransaction(block: suspend () -> R)

    coEvery { itemDao.deleteAll() } just Runs
    coEvery { itemDao.insertAll(any()) } just Runs
    coEvery { subItemDao.insertAll(any()) } just Runs

    repository.saveItems(testResponse)

    coVerifySequence {
        itemDao.deleteAll()
        itemDao.insertAll(testItems)
        subItemDao.insertAll(testSubItems)
    }
}

1 Ответ

0 голосов
/ 18 июня 2019

Сначала необходимо включить статические макеты для метода Android Room KTX withTransaction {} .Вам также нужно перехватить переданную ей лямбда-функцию suspend.Эта захваченная функция может быть просто вызвана, поэтому код внутри нее выполняется.Поскольку вы осмеиваете все вызовы базы данных, вам здесь не нужна реальная транзакция.

@Before
fun initMocks() {
  MockKAnnotations.init(this)

  mockkStatic(
            "androidx.room.RoomDatabaseKt"
  )

  val transactionLambda = slot<suspend () -> R>()
    coEvery { db.withTransaction(capture(transactionLambda)) } coAnswers {
      transactionLambda.captured.invoke()
    }
}

После этого вы сможете выполнить свой код в письменном виде.

...