[英]How do I invoke a callback in a unit test in Android?
I want to invoke a callback to assert the execution it makes.我想调用一个回调来断言它所做的执行。
I'm using MVVM in my app.我在我的应用程序中使用 MVVM。 In one of the view models I implemented, I want to make sure the ui state changes when a process is completed.在我实现的其中一个视图模型中,我想确保 ui state 在流程完成时发生变化。
In my HomeViewModel.kt
I have:在我的HomeViewModel.kt
中我有:
@HiltViewModel
class HomeViewModel
@Inject
constructor(
private val storageRepository: StorageRepository,
private val accountRepository: AccountRepository,
) : ViewModel() {
// First state of isLoading is true
var uiState = mutableStateOf(HomeUiState())
...
fun addListener() {
viewModelScope.launch {
storageRepository.addListener(
accountRepository.getUserId(),
::onDocumentEvent,
onComplete = {
uiState.value = uiState.value.copy(isLoading = false)
},
onError = {
error -> onAddListenerFailure(error)
}
)
}
}
And I want to write the test:我想写测试:
Given homeViewModel.addListener()给定homeViewModel.addListener()
When storageRepository.addListener(...) completes当storageRepository.addListener(...) 完成时
Then uiState.isLoading is false那么uiState.isLoading 为 false
I've been searching for some time now and I have found some people referring to using captors from mockito but nothing that applies to my case.我已经搜索了一段时间,发现有些人提到使用 mockito 中的捕获器,但没有任何内容适用于我的情况。
This is what I have now这就是我现在所拥有的
@OptIn(ExperimentalCoroutinesApi::class)
internal class HomeViewModelTest {
// mock repositories
@Mock lateinit var storageRepository: StorageRepository
@Mock lateinit var accountRepository: AccountRepository
@Mock lateinit var logRepository: LogRepository
// set dispatcher to be able to run tests
private val dispatcher = StandardTestDispatcher()
lateinit var callbackCaptor: KArgumentCaptor<() -> Unit>
@Before
fun setUp() {
MockitoAnnotations.openMocks(this)
Dispatchers.setMain(dispatcher)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `loading state is true when viewModel is created`() {
val homeViewModel = HomeViewModel(storageRepository, accountRepository, logRepository)
assertTrue(homeViewModel.uiState.value.isLoading)
}
@Test
fun `loading state is false when listener is added successfully`() {
val homeViewModel = HomeViewModel(storageRepository, accountRepository, logRepository)
callbackCaptor = argumentCaptor()
whenever(
storageRepository.addListener(
anyString(),
anyOrNull(),
callbackCaptor.capture(),
anyOrNull()
)
)
.thenAnswer { callbackCaptor.firstValue.invoke() }
homeViewModel.addListener()
// wait for mutable state to update
dispatcher.scheduler.advanceUntilIdle()
assertFalse(homeViewModel.uiState.value.isLoading)
}
}
Of course, I'm open to hearing solutions using something else than captors.当然,我愿意听取使用俘虏以外的东西的解决方案。
I think you are not initialising the captor, try following我认为您没有初始化捕获器,请尝试以下操作
@Test
fun `loading state is false when listener completes its process`() {
val homeViewModel = HomeViewModel(storageRepository, accountRepository, logRepository)
val callbackCaptor = argumentCaptor<() -> Unit>() //used kotlin mockito
whenever(storageRepository.addListener(anyString(), any(), callbackCaptor.capture(), any()))
.thenAnswer { callbackCaptor.firstValue.invoke() }
homeViewModel.addListener()
// wait for mutable state to update
dispatcher.scheduler.advanceUntilIdle()
assertFalse(homeViewModel.uiState.value.isLoading)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.