MainViewModelTest.kt 中的我的单元测试无法正常工作。似乎行 _recentTvShowList.update {licateRemoverSet.toList() } 没有更新。我已经模拟了存储库和 dao,所以我无法弄清楚为什么它不起作用。
MainViewModelTest.kt
@ExperimentalCoroutinesApi
class MainViewModelTest {
private lateinit var repository: TvShowsRepository
private lateinit var dao: TvShowCheckerDao
private val viewModel: MainViewModel by lazy { MainViewModel(repository) }
@ExperimentalCoroutinesApi
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
private val testModules = module {
single<TvShowsRepository> { mockk<TvShowsRepository>() }
viewModel { MainViewModel(get()) }
}
@ExperimentalCoroutinesApi
class MainDispatcherRule(private val dispatcher: TestDispatcher = StandardTestDispatcher()) :
TestWatcher() {
override fun starting(description: Description?) = Dispatchers.setMain(dispatcher)
override fun finished(description: Description?) = Dispatchers.resetMain()
}
@Before
fun setUp() {
repository = mockk(relaxed = true)
dao = mockk(relaxed = true)
startKoin { modules(testModules) }
}
@After
fun tearDown() {
stopKoin()
}
@ExperimentalCoroutinesApi
@Test
fun `tests getRecentTvShows() returns list of recent tv shows`() = runTest {
val repository: TvShowsRepository = mockk()
val tvShow1 = TvShow(
id = 1,
description = "Show 1",
title = "Description 1",
airDate = "https://example.com/show1.jpg"
)
val tvShow2 = TvShow(
id = 2,
description = "Show 2",
title = "Description 2",
airDate = "https://example.com/show2.jpg"
)
coEvery { dao.getRecentTvShows() } returns listOf(tvShow1, tvShow2)
coEvery { repository.getRecentTvShows() } returns flowOf(listOf(tvShow1, tvShow2))
viewModel.getRecentTvShows()
val expectedList = listOf(tvShow1, tvShow2)
viewModel.recentTvShowList.test {
assertEquals(expectedList, awaitItem())
}
}
}
在 MainViewModel.kt 中测试功能
suspend fun getRecentTvShows() {
val duplicateRemoverSet = mutableSetOf<TvShow>()
repository.getRecentTvShows().collect { tvShowList ->
tvShowList.forEach {
duplicateRemoverSet.add(it)
}
}
_recentTvShowList.update { duplicateRemoverSet.toList() }
}
完整的MainViewModel.kt
@OptIn(FlowPreview::class)
class MainViewModel(
private val repository: TvShowsRepository
) : ViewModel() {
private val _searchText = MutableStateFlow("")
val searchText = _searchText.asStateFlow()
private val _isSearching = MutableStateFlow(false)
val isSearching = _isSearching
.onStart { getTvShows() }
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(5000),
false
)
private val _isLoading = MutableStateFlow(false)
val isLoading = _isLoading.asStateFlow()
private val _isEpisodesLoading = MutableStateFlow(false)
val isEpisodesLoading = _isEpisodesLoading.asStateFlow()
private val _selectedTvShow = MutableStateFlow<TvShowExtended?>(null)
val selectedTvShow = _selectedTvShow.asStateFlow()
private val _selectedSeason = MutableStateFlow(listOf<TvShowSeasonEpisodes>())
val selectedSeason = _selectedSeason.asStateFlow()
private val _error = MutableStateFlow("")
val error = _error.asStateFlow()
private val _tvShowList = MutableStateFlow(listOf<TvShow>())
val tvShowList = searchText
.debounce(1_000L)
.onEach { _isSearching.update { true } }
.combine(_tvShowList) { text, tvShow ->
if (text.isBlank()) {
tvShow
} else {
tvShow.filter { it.searchTvShow(text) }
}
}.onEach { _isSearching.update { false } }
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(5000),
_tvShowList.value
)
private val _recentTvShowList = MutableStateFlow(listOf<TvShow>())
val recentTvShowList = _recentTvShowList.asStateFlow()
// init {
// viewModelScope.launch {
// getRecentTvShows()
// }
// }
fun onSearchTextChange(text: String) {
_searchText.value = text
viewModelScope.launch { getTvShows(text) }
}
private suspend fun getTvShows(query: String = ""): List<TvShow> {
val duplicateRemoverSet = mutableSetOf<Result>()
try {
val temp = repository.getTVShows(query).results
temp.forEach {
duplicateRemoverSet.add(it)
}
} catch (e: Exception) {
_error.update { e.localizedMessage ?: "No error found" }
}
val tvShowList = AppMapper.mapGetTvShowsApiResultToTvShowList(duplicateRemoverSet.toList())
_tvShowList.update { tvShowList }
return tvShowList
}
suspend fun getRecentTvShows() {
val duplicateRemoverSet = mutableSetOf<TvShow>()
repository.getRecentTvShows().collect { tvShowList ->
tvShowList.forEach {
duplicateRemoverSet.add(it)
}
}
_recentTvShowList.update { duplicateRemoverSet.toList() }
}
fun insertRecentTvShow(tvShow: TvShow) {
viewModelScope.launch {
repository.insertRecentTvShow(tvShow = tvShow)
}
}
fun getTvShowById(tvShowId: Int) {
viewModelScope.launch {
try {
_searchText.update { "" }
val apiResult = repository.getTVShowById(tvShowId)
val result = AppMapper.mapGetTvShowByIdApiResultToTvShow(apiResult)
_selectedTvShow.update { result }
} catch (e: Exception) {
_error.update { e.localizedMessage ?: "No error found" }
}
}
}
fun getTvShowSeasons(tvShowId: Int, seasonNumber: Int = 1) {
viewModelScope.launch {
_isEpisodesLoading.value = true
try {
val apiResult = repository.getTvShowSeason(tvShowId, seasonNumber)
val result = AppMapper.mapGetTvShowSeasonsApiResultToTvShowSeason(apiResult)
result.forEach {
it.isChecked = repository.getIsWatchedStatus(it.episodeId)
it.tvShowId = tvShowId
insertTvShowSeasonEpisodesToDB(it)
}
_selectedSeason.update { result }
} catch (e: Exception) {
_error.update { e.localizedMessage ?: "No error found" }
}
_isEpisodesLoading.value = false
}
}
fun getTvShowSeasonsOffline(tvShowId: Int, seasonSelected: Int) {
viewModelScope.launch {
_isEpisodesLoading.value = true
try {
val databaseResult = repository.getTvShowSeasonOffline(tvShowId, seasonSelected)
_selectedSeason.update { databaseResult }
} catch (e: Exception) {
_error.update { e.localizedMessage ?: "No error found" }
}
_isEpisodesLoading.value = false
}
}
private fun insertTvShowSeasonEpisodesToDB(tvShowSeasonEpisodes: TvShowSeasonEpisodes) {
viewModelScope.launch {
repository.insertTvShow(tvShowSeasonEpisodes)
}
}
fun updateIsWatchedState(episodeId: Int, isWatched: Boolean) {
viewModelScope.launch {
repository.updateIsWatchedStatus(episodeId = episodeId, isWatchedStatus = isWatched)
}
}
}
awaitItem()
将返回流中第一个发出的值。您可以尝试使用 expectMostRecentItem()
来获取最新的发射值吗?
viewModel.recentTvShowList.test {
assertEquals(expectedList, expectMostRecentItem())
}