I am trying to test ViewModel
to make sure livedata gets updated correctly. However when using ArgumentMatchers.any()
it fails with IllegalStateException
saying:
ArgumentMatchers.any(mViewModel.CountSubscriber::class.java) must not be null
@Test fun emitValueIfCountIs7() { doAnswer { invocation: InvocationOnMock -> val subscriber: mViewModel.CountSubscriber = invocation.getArgument(0) subscriber.onNext(7) null }.`when`(countUseCase).execute( ArgumentMatchers.any(mViewModel.CountSubscriber::class.java), ArgumentMatchers.any(Parameters::class.java) ) // When mViewModel.getCount() // Verify assert(mViewModel.countResponse.value != null) }
I am using Kotlin and have the following dependencies:
testImplementation 'junit:junit:4.12' testImplementation "org.mockito:mockito-inline:2.23.4" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0"
Here are my imports:
import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.nhaarman.mockitokotlin2.doAnswer import io.reactivex.Observable import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.ArgumentMatchers.any import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.mockito.invocation.InvocationOnMock
Strange thing is that it used to work before, and I don't know what has happened that could affect this.
Since Mockito any(Class) and anyInt family matchers perform a type check, thus they won't match null arguments. Instead use the isNull matcher.
anyString() does not work for null · Issue #185 · mockito/mockito · GitHub.
Mockito Argument Matcher - eq() When we use argument matchers, then all the arguments should use matchers. If we want to use a specific value for an argument, then we can use eq() method. when(mockFoo. bool(eq("false"), anyInt(), any(Object. class))).
Getting matchers to work with Kotlin can be a problem. If you have a method written in kotlin that does not take a nullable parameter, then we cannot match with it using Mockito.any(). This is because it can return void and this is not assignable to a non-nullable parameter.
If the method being matched is written in Java, then I think that it will work as all Java objects are implicitly nullable.
One possible solution would be to use a library like mockito-kotlin But you can solve this issue easily with a few lines of code yourself.
If you need typed any(type: Class)
private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
OR
You can use this matcher instead of Matchers.any() :
object MockitoHelper { fun <T> anyObject(): T { Mockito.any<T>() return uninitialized() } @Suppress("UNCHECKED_CAST") fun <T> uninitialized(): T = null as T }
and use MockitoHelper.anyObject()
instead of any()
in your kotlin tests.
You can find more information in this post: Using Mockito with Kotlin
There is a discussion about possible solutions in this post : Is it possible to use Mockito in Kotlin?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With