首页 > 解决方案 > AndroidTest,测试来自 ViewModel 的协程

问题描述

我正在运行一个向数据库中插入一个新词的集成测试,测试从 ViewModel 开始,经过 Repository,然后通过 DAO。

测试

@ExperminentalCoroutinesApi
@RunWith(AndroidJUnit4::class) 
class ViewModelIntegrationTest {
    
    // Runs background jobs on the mainthread. 
    @get:Rule
    val taskExecutorRule = InstantTaskExecutorRule()

    lateinit var wordDatabase: WordRoomDatabase
    lateinit var wordDao: WordDao
    lateinit var repository: IWordRepository
    lateinit var viewModel: MainViewModel
    lateinit var wordListObserver: Observer<List<Word>>

    @Before
    fun setup() {
        // Creates a test database so read and write doesn't affect the real database.
        wordDatabase = Room.inMemoryDatabaseBuilder(
            InstrumentationRegistry.getInstrumentation().context,
            WordRoomDatabase::class.java
        )
            .allowMainThreadQueries()
            .build()

        wordDao = wordDatabase.wordDao()
        repository = WordRepository(wordDao)

        // See notes below regarding dispatches
        viewModel = MainViewModel(repository, Dispatchers.Main)
    }

    @Test
    fun insertWord() = runBlocking {
        val word1 = Word("word1")
        
        // Test returns an error here, error is listed below. 
        viewModel.insertWord(word1)
        ...
    }

}

测试协程开发峰会说您应该始终对调度程序使用构造函数注入。

Codelab 测试 5.3.7,说使用 Dispatchers.Main 将协程移动到主线程。当使用 .allMainThreadQueries 构建数据库时,Room 将允许在 MainThread 上进行查询。视图模型

class MainViewModel @Inject constructor(
    var repository: IWordRepository, 
    @IoDispatcher var ioDispatcher: CoroutineDispatcher
) : ViewModel() {

    ...


    fun insertWord(word: Word) viewModelScope.launch(ioDispatcher) {
        repository.insert(word)
    }

}

这是返回的错误

org.mockito.exceptions.verification.TooManyActualInvocations: 
observer.onChanged(<Capturing argument>);
Wanted 1 time:
-> at com.example.words.main.MainViewModelTest$insertWord$1.invokeSuspend(MainViewModelTest.kt:81)
But was 2 times:
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
-> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)

如果直接调用存储库,此错误就会消失。这让我相信问题出在调度员身上。

标签: androidandroid-roomkotlin-coroutinesandroid-testing

解决方案


推荐阅读