Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito when clause not working in kotlin

Tags:

mockito

kotlin

I am trying to use mockito in kotlin. I created the following test:

class HeroesDataSourceTest {

    @Mock
    lateinit var heroesRepository: HeroesRepository
    @Mock
    lateinit var params: PageKeyedDataSource.LoadInitialParams<Int>
    @Mock
    lateinit var callback: PageKeyedDataSource.LoadInitialCallback<Int, Heroes.Hero>

    val hero = Heroes.Hero(1, "superman", "holasuperman", 1, null, null)
    val results = Arrays.asList(hero)
    val data = Heroes.Data(results)
    val dataResult = Heroes.DataResult(data)

    val compositeDisposable = CompositeDisposable()

    lateinit var heroesDataSource: HeroesDataSource
    private val heroesPublishSubject = PublishSubject.create<Heroes.DataResult>()

    @Before
    fun initTest(){
        MockitoAnnotations.initMocks(this)

    }

    @Test
    fun testLoadInitialSuccess(){
        `when`(heroesRepository.getHeroes(ArgumentMatchers.anyInt())).thenReturn(heroesPublishSubject.singleOrError())
        heroesDataSource = HeroesDataSource(heroesRepository, compositeDisposable)
        val testObserver = TestObserver<Heroes.DataResult>()
        heroesDataSource.loadInitial(params, callback)
        heroesPublishSubject.onNext(dataResult)
        testObserver.assertComplete()
    }

}

But when I execute it in the line when(heroesRepository.getHeroes(ArgumentMatchers.anyInt())).thenReturn(heroesPublishSubject.singleOrError()) it just enter to getHeroes method instead of mocking it (and for sure since heroesRepository is not initialized because is mocket the method fails). I use this tons of times in java and it never gave me a single problem. What I have to do in kotlin to mock it properly?

EDIT

Here I put also HeroesRepository class

open class HeroesRepository {

    val privateKey = "5009bb73066f50f127907511e70f691cd3f2bb2c"
    val publicKey = "51ef4d355f513641b490a80d32503852"
    val apiDataSource = DataModule.create()
    val pageSize = 20

    fun getHeroes(page: Int): Single<Heroes.DataResult> {
        val now = Date().time.toString()
        val hash = generateHash(now + privateKey + publicKey)
        val offset: Int = page * pageSize
        return apiDataSource.getHeroes(now, publicKey, hash, offset, pageSize)
    }

    fun generateHash(variable: String): String {
        val md = MessageDigest.getInstance("MD5")
        val digested = md.digest(variable.toByteArray())
        return digested.joinToString("") {
            String.format("%02x", it)
        }
    }
}
like image 585
Iban Arriola Avatar asked Jan 08 '19 08:01

Iban Arriola


People also ask

Does Mockito work with Kotlin?

Mockito has been around since the early days of Android development and eventually became the de-facto mocking library for writing unit tests. Mockito and Mockk are written in Java and Kotlin, respectively, and since Kotlin and Java are interoperable, they can exist within the same project.

How do I know if Mockito is working?

Mockito verify() method can be used to test number of method invocations too. We can test exact number of times, at least once, at least, at most number of invocation times for a mocked method. We can use verifyNoMoreInteractions() after all the verify() method calls to make sure everything is verified.

What is difference between @mock and @injectmock?

@Mock is used to declare/mock the references of the dependent beans, while @InjectMocks is used to mock the bean for which test is being created.

How do you mock a method in Kotlin?

mockk:mockk supports to mock top-level functions in Kotlin. Similar to extension functions, for top-level functions, Kotlin creates a class containing static functions under the hood as well, which in turn can be mocked.


1 Answers

Without adding another dependency, you can replace using the @Mock annotation with a helper function somewhere:

inline fun <reified T> mock(): T =
        Mockito.mock(T::class.java)

// To avoid having to use backticks for "when"
fun <T> whenever(methodCall: T): OngoingStubbing<T> =
        Mockito.`when`(methodCall)

Then in your test:

val heroesRepository: HeroesRepository = mock()

@Test
fun yourTest() {
    whenever(heroesRepository.getHeroes(ArgumentMatchers.anyInt()))
        .thenReturn(heroesPublishSubject.singleOrError())
}

Like you had before. This should work, because you're not expecting Mockito to deal with @Mock lateinit var, which it seems to be struggling with, and instead instantiating the mock yourself.

like image 60
Can_of_awe Avatar answered Nov 11 '22 18:11

Can_of_awe