android - 如何使用 Mockk 创建观察者
问题描述
您好,我有一个使用 Mockito 的单元测试,我将它的大部分转换为使用 Mockk,除了我想创建一个 android 生命周期观察者的部分
有效的 Mockito 版本
@Mock
private lateinit var dataObserver: Observer<Result<List<Character>>>
Mockk 版本不起作用
private var dataObserver: Observer<Result<List<Character>>> = mockk(relaxed = true)
当我使用 Mockk 进行上述操作时,我的测试用例失败并出现以下错误,当我使用 Mockito 版本时通过
错误信息
java.lang.AssertionError: Verification failed: call 1 of 1: Observer(#2).onChanged(eq(Success([Character(name=myName, img=image, occupation=[], status=status, nickname=nickName, appearance=[])])))) was not called
at io.mockk.impl.recording.states.VerifyingState.failIfNotPassed(VerifyingState.kt:66)
at io.mockk.impl.recording.states.VerifyingState.recordingDone(VerifyingState.kt:42)
at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:60)
at io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalCoVerify(API.kt:143)
at io.mockk.MockKKt.coVerify(MockK.kt:175)
at io.mockk.MockKKt.coVerify$default(MockK.kt:172)
at com.example.breakingbad.MainActivityViewModelTest$fetchCharacters$1.invokeSuspend(MainActivityViewModelTest.kt:76)
完整的测试用例
package com.example.breakingbad
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.breakingbad.data.DataRepository
import com.example.breakingbad.model.Character
import com.example.breakingbad.viewModel.MainActivityViewModel
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.*
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
//@RunWith(MockitoJUnitRunner::class)
@ExperimentalCoroutinesApi
class MainActivityViewModelTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
private val testDispatcher = TestCoroutineDispatcher()
private val testCoroutineScope = TestCoroutineScope(testDispatcher)
private val dataRepository: DataRepository = mockk(relaxed = true)
private val mainActivityViewModel = MainActivityViewModel(dataRepository)
// @Mock
// private lateinit var dataObserver: Observer<Result<List<Character>>>
private var dataObserver: Observer<Result<List<Character>>> = mockk(relaxed = true)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
}
@After
fun cleanup() {
Dispatchers.resetMain()
testCoroutineScope.cleanupTestCoroutines()
}
@Test
fun fetchCharacters() {
testCoroutineScope.launch {
coEvery { dataRepository.getCharacters() } returns Result.success(arrayListOf(Character(
name = "myName",
img = "image",
occupation = arrayListOf(),
status = "status",
nickname = "nickName",
appearance = arrayListOf()
)))
mainActivityViewModel.fetchCharacters()
coVerify { dataRepository.getCharacters() }
coVerify { dataObserver.onChanged(
Result.success(listOf(Character (
name = "myName",
img = "image",
occupation = arrayListOf(),
status = "status",
nickname = "nickName",
appearance = arrayListOf()
)))
) }
mainActivityViewModel.charactersLiveData.removeObserver(dataObserver)
}
}
}
如何使用 Mockk 使测试用例通过?我究竟做错了什么?
编辑
视图模型
class MainActivityViewModel @Inject constructor(
private val dataRepository: DataRepository
): ViewModel() {
private val _charactersLiveData = MutableLiveData<Result<ArrayList<Character>>>()
val charactersLiveData: LiveData<Result<ArrayList<Character>>> = _charactersLiveData
fun fetchCharacters() {
viewModelScope.launch(Dispatchers.IO) {
_charactersLiveData.postValue(dataRepository.getCharacters())
}
}
}
解决方案
推荐阅读
- laravel - vuejs中的标题标签更改
- android - 为所有人删除消息
- jquery - 带有localStorage的jQuery单击功能不起作用
- python - 我得到 ModuleNotFoundError: No module named 'Cython' 尝试制作扩展时
- visual-studio-code - Visual Studio Code Live Share 自动完成非常延迟
- flutter - 在 Flutter 中实现通知逻辑
- python - 在 Python 3 中打印给定系列的谐波系列
- linux - 即使在步骤完成后,如何继续从 Jenkins 管道运行命令/bat 文件?
- python - 如何从 read_game 的最终位置获得棋盘?
- javascript - 将字符串转换为数字,具体取决于它们是否具有后缀,例如 1.5K