预期- 在本地单元测试中保存嵌套的 LiveData 值,然后断言它们的值。
观察到- 在生产代码中成功观察到在 ViewModel 中保存嵌套的 LiveData 值,但在本地单元测试中失败。这可能是由于与在 Android 环境中运行相比,本地单元测试中缺少线程。
LOADING
,CONTENT
和ERROR
用于当用户选择的内容以打开(LCE)的条件。NotifyItemChangedEffect
保存LiveData状态以更新视图。NotifyItemChangedEffect
保存在函数内部以保存发送到视图的内容。只有在这种CONTENT
情况下,所选项目才会发送到保存了 LiveData 对象的视图ContentToPlay
。LOADING
,CONTENT
和ERROR
,虽然ContentToPlay
是只有在成功的返回CONTENT
状态。内容视图模型.kt
is ContentSelected -> {
_feedViewState.value = _feedViewState.value?.copy(
// LiveData value for ContentToPlay initiated here.
contentToPlay = switchMap(getAudiocast(contentSelected)) { lce ->
liveData {
when (lce) {
is Loading ->
_viewEffect.value = _viewEffect.value?.copy(
notifyItemChanged = liveData {
emit(Event(NotifyItemChangedEffect(...)))
})
is Lce.Content -> {
_viewEffect.value = _viewEffect.value?.copy(
notifyItemChanged = liveData {
emit(Event(NotifyItemChangedEffect(...)))
})
// LiveData value for ContentToPlay saved here.
emit(Event(lce.packet))
}
is Error -> {
_viewEffect.value = _viewEffect.value?.copy(
notifyItemChanged = liveData {
emit(Event(NotifyItemChangedEffect(...)))
})
_viewEffect.value = _viewEffect.value?.copy(
snackBar = liveData {
emit(Event(SnackBarEffect(...)))
})
}
}
}
})
...
}
ContentToPlay
不返回LOADING
和ERROR
条件。NotifyItemChangedEffect
未保存在单元测试中,这会更新每个 LCE 条件中的视图。此代码在为 保存的 LiveData 内执行ContentToPlay
。此模式已记录并在生产中工作。播放内容测试.kt
@ExtendWith(InstantExecutorExtension::class)
class PlayContentTests {
@ParameterizedTest
@MethodSource("FeedLoad")
fun `Play Content`(test: PlayContentTest) = runBlocking {
// ViewModel method included to initiate ContentSelected event.
...
when (test.lceState) {
LOADING ->
assertThat(contentViewModel.viewEffect.getOrAwaitValue().notifyItemChanged.getOrAwaitValue().peekEvent()).isEqualTo(
NotifyItemChangedEffect(...))
CONTENT -> {
assertThat(contentViewModel.feedViewState.getOrAwaitValue().contentToPlay.getOrAwaitValue().peekEvent()).isEqualTo(
ContentToPlay(...))
assertThat(contentViewModel.viewEffect.getOrAwaitValue().notifyItemChanged.getOrAwaitValue().peekEvent()).isEqualTo(
NotifyItemChangedEffect(...))
}
ERROR -> {
assertThat(contentViewModel.feedViewState.getOrAwaitValue().contentToPlay.getOrAwaitValue().peekEvent()).isEqualTo(
ContentToPlay(...))
assertThat(contentViewModel.viewEffect.getOrAwaitValue().notifyItemChanged.getOrAwaitValue().peekEvent()).isEqualTo(
NotifyItemChangedEffect(...))
}
}
}
}
保存ContentToPlay
LiveData 值或null
在 ViewModel 的所有 LCE 条件中,以确保同步返回值以进行本地单元测试。
注意- 此策略的缺点是它ContentToPlay
向生产代码中的视图发出不必要的值,这并不理想,但似乎不是主要问题。
内容视图模型.kt
_feedViewState.value = _feedViewState.value?.copy(contentToPlay =
switchMap(getAudiocast(contentSelected)) { lce ->
liveData {
when (lce) {
is Loading -> {
setContentLoadingStatus(contentSelected.content.id, View.VISIBLE)
_viewEffect.value = _viewEffect.value?.copy(
notifyItemChanged = liveData {
emit(Event(NotifyItemChangedEffect(contentSelected.position)))
})
// Empty ContentToPlay saved.
emit(Event(null))
}
is Lce.Content -> {
setContentLoadingStatus(contentSelected.content.id, View.GONE)
_viewEffect.value = _viewEffect.value?.copy(
notifyItemChanged = liveData {
emit(Event(NotifyItemChangedEffect(contentSelected.position)))
})
// ContentToPlay saved.
emit(Event(lce.packet))
}
is Error -> {
setContentLoadingStatus(contentSelected.content.id, View.GONE)
_viewEffect.value = _viewEffect.value?.copy(
notifyItemChanged = liveData {
emit(Event(NotifyItemChangedEffect(contentSelected.position)))
})
if (lce.packet.filePath.equals(TTS_CHAR_LIMIT_ERROR))
_viewEffect.value = _viewEffect.value?.copy(
snackBar = liveData {
emit(Event(SnackBarEffect(TTS_CHAR_LIMIT_ERROR_MESSAGE)))
})
else _viewEffect.value = _viewEffect.value?.copy(
snackBar = liveData {
emit(Event(SnackBarEffect(CONTENT_PLAY_ERROR)))
})
// Empty ContentToPlay saved.
emit(Event(null))
}
}
}
})
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句