Android:从viewmodel更新数据库并对其进行单元测试

lrpiutwd  于 2023-05-15  发布在  Android
关注(0)|答案(2)|浏览(180)

我的视图模型中有一个方法可以重置数据库中的行。

fun resetScores() {
    viewModelScope.launch {
       for(player in players){ 
           
           player.level = 1
           player.score = 0
           playerDao.updatePlayer(player) // updates the DB
       }
    }
}

var players = mutableListOf<Player>() -- > players is a mutable list

我有这个单元测试来测试这个方法

@Test
fun testResetScores() {
    val context = ApplicationProvider.getApplicationContext<Context>()
    val viewModel = PlayerViewModel(Phase10DataBase.getDatabase(context).playerDao)
    viewModel.players = mutableListOf(Player(1,"Player1",5,100),
        Player(2,"Player2",5,100),
        Player(3,"Player3",5,100))
    assertEquals(viewModel.players.get(1).score, 100)
    viewModel.resetScores()
    assertEquals(viewModel.players.get(1).score, 100)
}

这个测试通过了,而我预计它会失败。看起来测试在调用assert之前没有等待async DB操作完成。测试它的正确方法是什么,或者实际代码resetScore是否需要更新?

lymgl2op

lymgl2op1#

使用runBlocking它阻塞直到协程完成

@Test
fun testResetScores() = runBlocking {
    val context = ApplicationProvider.getApplicationContext<Context>()
    val viewModel = PlayerViewModel(Phase10DataBase.getDatabase(context).playerDao)
    viewModel.players = mutableListOf(Player(1,"Player1",5,100),
        Player(2,"Player2",5,100),
        Player(3,"Player3",5,100))
    assertEquals(viewModel.players.get(1).score, 100)
    viewModel.resetScores()
    assertEquals(viewModel.players.get(1).score, 100)
}
xqkwcwgp

xqkwcwgp2#

也许这对提问者来说太晚了,但希望这对其他人有帮助。
发生这种行为是因为我们在viewModel.resetScores()内部创建了一个新的协程,与assertEquals同时运行,并且在我们对viewModel.players进行更改之前调用了assertEqual
为了解决这个问题,我们可以使用advanceUntilIdle来等待所有任务完成:

@Test
fun testResetScores() {
    Dispatchers.setMain(dispatcher)
    val scope: TestScope = TestScope(dispatcher)
    scope.runTest {
        val viewModel = TestViewModel()
        viewModel.players = mutableListOf(
            Player(1, "Player1", 5, 100),
            Player(2, "Player2", 5, 100),
            Player(3, "Player3", 5, 100)
        )
        assertEquals(viewModel.players[1].score, 100)
        viewModel.resetScores()
        advanceUntilIdle()
        assertEquals(viewModel.players[1].score, 100)
    }
}

相关问题