Junit Mocked suspend函数在Mockito中返回null

Junit Mocked suspend函数在Mockito中返回null,junit,kotlin,mockito,kotlinx.coroutines,Junit,Kotlin,Mockito,Kotlinx.coroutines,我使用Mockito模拟了一个挂起的函数,但它返回null @Test fun `when gps not enabled observer is notified`() = runBlocking { // arrange `when`(suspendingLocationService.getCurrentLocation()).thenReturn(result) // <- when called this returns null // act

我使用Mockito模拟了一个挂起的函数,但它返回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()
}
两个项目都使用

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

这是我的测试,其中mock返回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)
                }
        }
    }
}
override suspend fun textChanged(newText: String?) {
    val product = suspendingNetworkProvider.getProduct(newText)
    view?.update(product.name)
}
这是我正在嘲弄的界面

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

在第一个示例中我没有做的是,Mockito特别支持
挂起
函数,但在Kotlin 1.3中,内部实现协同路由的方式发生了一些变化,因此旧版本的Mockito不再支持Kotlin 1.3编译的
挂起
方法。和
kotlinx.coroutines
从1.0.0版开始使用kotlin1.3

Mockito只添加了相应的支持,因此更新Mockito版本将有所帮助。

首先获取并 在mockito中,当您想要模拟挂起函数时,可以使用此代码:

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

最上面的答案是正确的答案。我升级到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
})

我正在使用org.mockito:mockito核心:3.3.0,我仍然有这个问题mockito 3.3.3,还有同样的问题@iori24您找到解决方法了吗?