android - 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)
如果直接调用存储库,此错误就会消失。这让我相信问题出在调度员身上。