模拟的暂停功能在Mockito中返回null

时间:2018-11-01 10:02:07

标签: junit kotlin mockito kotlinx.coroutines

我有一个使用Mockito模拟的暂停函数,但返回的是空值

两个项目都使用

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

示例1

这是我的测试,其中的模拟返回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()
}

我的演示者中具有以下实现

  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)
                }
        }
    }
}

无论如何,我对下面类似的实现非常满意

示例2

下面的测试确实通过了,并且正确的功能确实对产品做出了响应

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

    // act
    presenter.textChanged("testString")

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

这是演示者的实现

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

这是我在嘲笑的界面

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

在第一个示例中我没有做什么

3 个答案:

答案 0 :(得分:6)

Mockito对suspend函数有特殊的支持,但是在Kotlin 1.3中,协程的内部实现方式发生了一些变化,因此Mockito的较旧版本不再能够识别Kotlin 1.3编译的suspend方法。并且kotlinx.coroutines从1.0.0版开始使用Kotlin 1.3。

Mockito已添加了相应的支持,但仅支持since version 2.23,因此更新Mockito版本将有所帮助。

答案 1 :(得分:0)

先获得Mockito-kotlin,然后 在 mockito 中,当您要模拟悬浮功能时可以使用此代码:

        val mockedObject: TestClass = mock()
        mockedObject.stub {
            onBlocking { suspendFunction() }.doReturn(true)
        }

答案 2 :(得分:-1)

最佳答案是正确答案。我升级到mockito 2.23并且能够成功地做到这一点,没有遇到空值的问题。我在使用 mockito 2.21 时遇到了同样的问题

class Parser {
suspend fun parse(responseBody: ByteArray) : Result = coroutineScope {/*etc*/}
}

val expectedResult = Mockito.mock(Result::class.java)
Mockito.`when`(mockParser.parse(byteArrayOf(0,1,2,3,4))).thenReturn(coroutineScope {
 expectedResult
})