android - 使用 MockK 测试 LiveData 和协程
问题描述
我有这个视图模型:
class MyViewModel(private val myUseCase: MyUseCase) : ViewModel() {
val stateLiveData = MutableLiveData(State.IDLE)
fun onButtonPressed() {
viewModelScope.launch {
stateLiveData.value = State.LOADING
myUseCase.loadStuff() // Suspend
stateLiveData.value = State.SUCCESS
}
}
}
我想编写一个测试来检查状态是否真的LOADING
在myUseCase.loadStuff()
运行时。我正在为此使用 MockK。这是测试类:
@ExperimentalCoroutinesApi
class MyViewModelTest {
@get:Rule
val rule = InstantTaskExecutorRule()
private lateinit var myUseCase: MyUseCase
private lateinit var myViewModel: MyViewModel
@Before
fun setup() {
myUseCase = mockkClass(MyUseCase::class)
myViewModel = MyViewModel(myUseCase)
}
@Test
fun `button click should put screen into loading state`() = runBlockingTest {
coEvery { myUseCase.loadStuff() } coAnswers { delay(2000) }
myViewModel.onButtonPressed()
advanceTimeBy(1000)
val state = myViewModel.stateLiveData.value
assertEquals(State.LOADING, state)
}
}
它失败:
java.lang.AssertionError:
Expected :LOADING
Actual :IDLE
我怎样才能解决这个问题?
解决方案
我只需要在测试类中进行一些更改即可使其通过:
@ExperimentalCoroutinesApi
class MyViewModelTest {
@get:Rule
val rule = InstantTaskExecutorRule()
private val dispatcher = TestCoroutineDispatcher()
private lateinit var myUseCase: MyUseCase
private lateinit var myViewModel: MyViewModel
@Before
fun setup() {
Dispatchers.setMain(dispatcher)
myUseCase = mockkClass(MyUseCase::class)
myViewModel = MyViewModel(myUseCase)
}
@After
fun cleanup() {
Dispatchers.resetMain()
}
@Test
fun `button click should put screen into loading state`() {
dispatcher.runBlockingTest {
coEvery { myUseCase.loadStuff() } coAnswers { delay(2000) }
myViewModel.onButtonPressed()
// This isn't even needed.
advanceTimeBy(1000)
val state = myViewModel.stateLiveData.value
assertEquals(State.LOADING, state)
}
}
}
视图模型根本不需要更改!:D
感谢 Kiskae 提供如此有用的建议!