gpt4 book ai didi

android - 测试协程和 LiveData : Coroutine result not reflected on LiveData

转载 作者:行者123 更新时间:2023-11-30 04:59:08 28 4
gpt4 key购买 nike

我是测试新手,我想学习如何使用 MVVM 模式测试协程。我刚刚关注了 https://github.com/android/architecture-samples 项目并做了一些更改(删除了远程源)。但是在测试 ViewModel 以从存储库中获取数据时,它一直失败并出现此错误。

value of    : iterable.size()
expected : 3
but was : 0
iterable was: []
Expected :3
Actual :0

下面是我的 ViewModel 测试类,不知道我遗漏了什么。此外,在模拟存储库时,我可以在打印 taskRepository.getTasks() 时从中获得预期结果,它只是在调用 loadTasks( )

View 模型测试

@ExperimentalCoroutinesApi
@RunWith(MockitoJUnitRunner::class)
class TasksViewModelTest {

private lateinit var tasksViewModel: TasksViewModel

val tasksRepository = mock(TasksRepository::class.java)

@ExperimentalCoroutinesApi
@get:Rule
var mainCoroutineRule = TestMainCoroutineRule()

// Executes each task synchronously using Architecture Components.
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()

@Before
fun setupViewModel() {
tasksViewModel = TasksViewModel(tasksRepository)
}

@Test
fun whenLoading_hasListOfTasks() = runBlockingTest {
val task1 = Task("title1", "description1")
val task2 = Task("title2", "description2")
val task3 = Task("title3", "description3")
`when`(tasksRepository.getTasks()).thenReturn(Result.Success(listOf(
task1,
task2,
task3
)))

tasksViewModel.loadTasks()

val tasks = LiveDataTestUtil.getValue(tasksViewModel.tasks)
assertThat(tasks).hasSize(3)
}
}

任务 View 模型

class TasksViewModel @Inject constructor(
private val repository: TasksRepository
) : ViewModel() {

private val _tasks = MutableLiveData<List<Task>>().apply { value = emptyList() }
val tasks: LiveData<List<Task>> = _tasks

fun loadTasks() {
viewModelScope.launch {
val tasksResult = repository.getTasks()

if (tasksResult is Success) {
val tasks = tasksResult.data
_tasks.value = ArrayList(tasks)
}
}
}
}

下面列出了帮助类,我只是从示例项目中复制了相同的类。

LiveDataTestUtil

object LiveDataTestUtil {

/**
* Get the value from a LiveData object. We're waiting for LiveData to emit, for 2 seconds.
* Once we got a notification via onChanged, we stop observing.
*/
fun <T> getValue(liveData: LiveData<T>): T {
val data = arrayOfNulls<Any>(1)
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data[0] = o
latch.countDown()
liveData.removeObserver(this)
}
}
liveData.observeForever(observer)
latch.await(2, TimeUnit.SECONDS)

@Suppress("UNCHECKED_CAST")
return data[0] as T
}
}

主协程规则

@ExperimentalCoroutinesApi
class TestMainCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {

override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(this.coroutineContext[ContinuationInterceptor] as CoroutineDispatcher)
}

override fun finished(description: Description?) {
super.finished(description)
Dispatchers.resetMain()
}
}

最佳答案

事实证明这是 mockito 的问题,我有一个旧版本,我发现有一个名为 mockito-kotlin 的库可以简化测试协程,如 here 所述.然后我将我的代码修改为这个,它运行良好。

tasksRepository.stub {
onBlocking { getTasks() }.doReturn(Result.Success(listOf(task1, task2, task3)))
}

关于android - 测试协程和 LiveData : Coroutine result not reflected on LiveData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58534129/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com