解决SignUpViewModel测试中的TooManyActualInvocations错误
问题解决:SignUpViewModel测试中的TooManyActualInvocations错误
错误原因
测试代码中手动调用了一次repository.registerAccount(dummyName, dummyEmail, dummyPassword),而执行signUpViewModel.registerAccount时,ViewModel内部又会调用一次该方法,导致该方法实际被执行2次,但Mockito的verify默认只期望方法被调用1次,因此触发了TooManyActualInvocations错误。
另外,测试中直接将LiveData对象与dummyRegisterResponse比较是错误的,应该获取LiveData的实际值进行断言。
修正后的测试代码
@ExperimentalCoroutinesApi @RunWith(MockitoJUnitRunner::class) class SignUpViewModelTest { @get:Rule val instantExecutorRule = InstantTaskExecutorRule() @get:Rule var mainDispatcherRule = MainDispatcherRule() @Mock private lateinit var repository: Repository private lateinit var signUpViewModel: SignUpViewModel private val dummyRegisterResponse = DataDummy.generateDummyRegisterResponse() private val dummyName = "Full Name" private val dummyEmail = "email@mail.com" private val dummyPassword = "password" @Before fun setUp() { signUpViewModel = SignUpViewModel(repository) } @Test fun standartTest() = runTest { val obj = MutableLiveData<RegisterResponse>() obj.value = dummyRegisterResponse // 预设Repository的registerResponse返回值 Mockito.`when`(repository.registerResponse).thenReturn(obj) // 调用ViewModel的方法,内部会触发Repository的registerAccount signUpViewModel.registerAccount(dummyName, dummyEmail,dummyPassword) // 验证Repository的registerAccount只被调用一次 verify(repository).registerAccount(dummyName, dummyEmail, dummyPassword) // 获取LiveData的值并断言 val actualResponseValue = signUpViewModel.registerResponse.value Assert.assertNotNull(actualResponseValue) Assert.assertEquals(dummyRegisterResponse, actualResponseValue) } }
关键修正点
- 移除手动调用的
repository.registerAccount:ViewModel的registerAccount方法已经会触发该调用,无需手动执行。 - 修正LiveData断言逻辑:通过
signUpViewModel.registerResponse.value获取LiveData的当前值,再与假数据比较。 - 保持Mock预设的顺序:先通过
Mockito.when预设Repository的返回值,再调用ViewModel的方法,确保Mock行为生效。
额外说明
由于Repository的registerAccount是基于Retrofit的异步回调实现,在测试Mock对象时,我们不需要关心内部的异步逻辑,只需要预设registerResponse的返回值即可,因为Mock对象不会执行真实的网络请求逻辑。
内容的提问来源于stack exchange,提问作者Fauziah -
相关产品推荐
相关产品推荐

