hello I'm having trouble testing with a viewmodel like this, how do I make a test with a viewmodel like this because i've had an error several times. where I explained the error below
class SignUpViewModel(private val pref: Repository) : ViewModel() {
val registerResponse: LiveData<RegisterResponse> = pref.registerResponse
val toastText: LiveData<String> = pref.toastText
fun registerAccount(name: String, email: String, password: String) {
viewModelScope.launch {
pref.registerAccount(name, email, password)
}
}}
this is the test i made but it failed and i don't know where the error is... for the tests I did using the repositor and viewmodel
@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 protected]"
private val dummyPassword = "password"
@Before
fun setUp() {
signUpViewModel = SignUpViewModel(repository)
}
@Test
fun standartTest() = runTest {
val obj = MutableLiveData<RegisterResponse>()
obj.value = dummyRegisterResponse
repository.registerAccount(dummyName, dummyEmail, dummyPassword)
Mockito.`when`(repository.registerResponse).thenReturn(obj)
signUpViewModel.registerAccount(dummyName, dummyEmail,dummyPassword)
val actualResponse = signUpViewModel.registerResponse
verify(repository).registerAccount(dummyName, dummyEmail, dummyPassword)
Assert.assertNotNull(actualResponse)
Assert.assertEquals(dummyRegisterResponse, actualResponse)
}}
after testing the code above, the results are like this and the error is like this and the error is like this. I'm confused where is the error
org.mockito.exceptions.verification.TooManyActualInvocations:
repository.registerAccount(
"Full Name",
"[email protected]",
"password");
Wanted 1 time:
-> at com.example.mysubmission_intermediate.Remote.Repository.registerAccount(Repository.kt:62)
But was 2 times:
-> at SignUpViewModelTest$standartTest$1.invokeSuspend(SignUpViewModelTest.kt:50)
-> at com.example.mysubmission_intermediate.UI.SignUpViewModel$registerAccount$1.invokeSuspend(SignUpViewModel.kt:16)
this is the repository i am using and connected to the viewmodel i am using
class Repository private constructor(
private val pref: UserPreference,
private val apiService: ApiService
) {
private val _registerResponse = MutableLiveData<RegisterResponse>()
val registerResponse: LiveData<RegisterResponse> = _registerResponse
fun registerAccount(name: String, email: String, password: String) {
val client = apiService.userRegister(name, email, password)client.enqueue(object: Callback<RegisterResponse> {
override fun onResponse(
call: Call<RegisterResponse>,
response: Response<RegisterResponse>
) {
if (response.isSuccessful && response.body() !=null) {
_registerResponse.value = response.body()
_toastText.value = response.body()?.message
} else {
_toastText.value = response.message().toString()
Log.e(TAG, "onFailure: ${response.message()}, ${response.body()?.message.toString()}" )
}
}
override fun onFailure(call: Call<RegisterResponse>, t: Throwable) {
_toastText.value = t.message.toString()
Log.e(TAG, "onFailure: ${t.message.toString()}")
}
})
}
and this is dummy data that i use for testing
object DataDummy {
fun generateDummyRegisterResponse(): RegisterResponse {
return RegisterResponse(
false,
"success"
)
}}
please help me how can i solve this error
CodePudding user response:
Your verify call of verify(repository).registerAccount(dummyName, dummyEmail, dummyPassword)
checks that registerAccount is called exactly once. It isn't- it's called twice. What you need to decide is if calling it twice is ok or not. If it's ok, use verify(repository, atLeastOnce())
which will pass if its called at least 1 time (but can be more often).
If its not ok and you really want it once- you need to figure out why it was called twice. The two calls were
at SignUpViewModelTest$standartTest$1.invokeSuspend(SignUpViewModelTest.kt:50)
-> at com.example.mysubmission_intermediate.UI.SignUpViewModel$registerAccount$1.invokeSuspend(SignUpViewModel.kt:16)
Figure out which is wrong, and fix either your test or code so it doesn't happen