如何使用MockK在Android中测试Kotlin挂起调用



我正在尝试使用Android应用程序进行TDD。我是用Kotlin写的,因此我求助于MockK进行测试,但有一件事(目前(我还没能找到如何做:测试一个挂起调用。

我为ViewModel中的LiveData值编写了一个测试,并使其发挥了作用。然而,当我在组合中添加coroutines时,我开始得到";方法getMainLooper not mocked";消息

这是我的代码:

ToDoListViewModelTest.kt

class ToDoListViewModelTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@MockK
private lateinit var toDoListLiveDataObserver: Observer<List<ToDoItem>>
@MockK
private lateinit var getToDoItemsUseCase: GetToDoItemsUseCase
@Before
fun setUp() {
MockKAnnotations.init(this)
every { toDoListLiveDataObserver.onChanged(any()) } answers { nothing }
}
@Test
fun toDoList_listItems_noItems() = runBlocking {
coEvery { getToDoItemsUseCase() } coAnswers { emptyList<ToDoItem>() }
val toDoListViewModel = ToDoListViewModel(getToDoItemsUseCase)
toDoListViewModel.toDoItemList.observeForever(toDoListLiveDataObserver)
toDoListViewModel.updateItemList()
assertEquals(0, toDoListViewModel.toDoItemList.value?.size)
}
}

ToDoListViewModel.kt

class ToDoListViewModel(private val getToDoItemsUseCase: GetToDoItemsUseCase) : ViewModel() {
private val _toDoItemList: MutableLiveData<List<ToDoItem>> = MutableLiveData()
val toDoItemList : LiveData<List<ToDoItem>> = _toDoItemList
fun updateItemList() {
viewModelScope.launch(Dispatchers.IO) {
_toDoItemList.value = getToDoItemsUseCase()
}
}
}

GetToDoItemsUseCase.kt

class GetToDoItemsUseCase {
suspend operator fun invoke(): List<ToDoItem> {
return listOf()
}
}

我尝试过的东西:

  • 添加"@RunWith(BlockJUnit4ClassRunner::class(":没有变化
  • 添加";testOptions{unitTests.returnDefaultValues=true}"到Gradle文件:Looper错误消失了,但来自LiveData的值为null,而不是"中指定的空列表;coEvery;呼叫
  • 呼叫";Dispatchers.setMain(newSingleThreadContext("UI线程"((:与前面的情况相同,从LiveData获取null

我在测试方面没有太多经验,而且我已经没有选择了。我觉得我肯定需要社区的帮助;(

此外,如果由于某种原因,我的设置不正确(应该使用MockK以外的东西,或其他一些测试框架…(,请对此发表评论。关于这一点,我还有很多需要学习的地方。

使用postValue_toDoItemList.postValue(getToDoItemsUseCase())

基于文件:

setValue((:

设置值。如果有活动的观察者,则值为发送给他们。必须从主线程调用此方法。

postValue((:

将任务发布到主线程以设置给定值。如果你打电话在主线程执行发布的任务,则只会调度最后一个值。

最新更新