Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocked suspend function returns null in Mockito

I have a suspending functions that I have mocked, using Mockito but it is returning null

both projects use

'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'

Example 1

here is my test in which the mock is returning null

@Test
fun `when gps not enabled observer is notified`() = runBlocking {
    // arrange
    `when`(suspendingLocationService.getCurrentLocation()).thenReturn(result) // <- when called this returns null

    // act
    presenter.onStartShopButtonClick()

    // assert
    verify(view).observer
    verify(observer).onPrepareShop()
}

I have the below implementation in my presenter

  override suspend fun onStartShopButtonClick() {
    val result = suspendingLocationService.getCurrentLocation() // <- in my test result is null!!!!!!
    view?.apply {
        observer?.onPrepareShop()
        when {
            result.hasGivenPermission == false -> observer?.onStartShop(StoreData(), APIError(APIError.ErrorType.NO_PERMISSION))
            result.hasGPSEnabled == false -> observer?.onStartShop(StoreData(), APIError(APIError.ErrorType.GPS_NOT_ENABLED))
            result.latitude != null && result.longitude != null ->
                storeLocationService.getCurrentStore(result.latitude, result.longitude) { store, error ->
                    observer?.onStartShop(store, error)
                }
        }
    }
}

however I have what I believe to a very similar implementation that is working below

Example 2

The below test does pass and the correct the function does respond with a product

@Test
fun `suspending implementation updates label`() = runBlocking {
    // arrange
    `when`(suspendingProductProvider.getProduct("testString")).thenReturn(product)

    // act
    presenter.textChanged("testString")

    // assert
    verify(view).update(product.name)
}

here is the implementation of the presenter

override suspend fun textChanged(newText: String?) {
    val product = suspendingNetworkProvider.getProduct(newText)
    view?.update(product.name)
}

here is the interface I am mocking

interface SuspendingProductProvider {
    suspend fun getProduct(search: String?): Product
}

what I am not doing in the first example

like image 314
Mark Gilchrist Avatar asked Nov 01 '18 10:11

Mark Gilchrist


2 Answers

first get Mockito-kotlin and in mockito you can use this code when you want to mock suspend functions :

        val mockedObject: TestClass = mock()
        mockedObject.stub {
            onBlocking { suspendFunction() }.doReturn(true)
        }
like image 141
Vahab Ghadiri Avatar answered Oct 16 '22 14:10

Vahab Ghadiri


Mockito has a special support for suspend functions, but in Kotlin 1.3 there were some changes in how coroutines are implemented internally, so older versions of Mockito are no longer recognize suspend methods compiled by Kotlin 1.3. And kotlinx.coroutines use Kotlin 1.3 since version 1.0.0.

Corresponding support was added to Mockito, but only since version 2.23, so updating your Mockito version will help.

like image 36
qwwdfsad Avatar answered Oct 16 '22 14:10

qwwdfsad