Mockito 中的模拟挂起函数 returns null
Mocked suspend function returns null in Mockito
我使用 Mockito 模拟了一个挂起函数,但它返回 null
两个项目都使用
'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)
}
这里是presenter的实现
override suspend fun textChanged(newText: String?) {
val product = suspendingNetworkProvider.getProduct(newText)
view?.update(product.name)
}
这是我模拟的界面
interface SuspendingProductProvider {
suspend fun getProduct(search: String?): Product
}
我在第一个例子中没有做什么
Mockito 对 suspend
函数有特殊的支持,但在 Kotlin 1.3 中协程的内部实现方式发生了一些变化,因此旧版本的 Mockito 不再识别由 suspend
编译的方法科特林 1.3。 kotlinx.coroutines
从 1.0.0 版本开始使用 Kotlin 1.3。
已为 Mockito 添加了相应的支持,但仅 since version 2.23,因此更新您的 Mockito 版本会有所帮助。
先得到Mockito-kotlin然后
在 mockito 中,当你想模拟 suspend 函数时可以使用此代码 :
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
})
我使用 Mockito 模拟了一个挂起函数,但它返回 null
两个项目都使用
'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)
}
这里是presenter的实现
override suspend fun textChanged(newText: String?) {
val product = suspendingNetworkProvider.getProduct(newText)
view?.update(product.name)
}
这是我模拟的界面
interface SuspendingProductProvider {
suspend fun getProduct(search: String?): Product
}
我在第一个例子中没有做什么
Mockito 对 suspend
函数有特殊的支持,但在 Kotlin 1.3 中协程的内部实现方式发生了一些变化,因此旧版本的 Mockito 不再识别由 suspend
编译的方法科特林 1.3。 kotlinx.coroutines
从 1.0.0 版本开始使用 Kotlin 1.3。
已为 Mockito 添加了相应的支持,但仅 since version 2.23,因此更新您的 Mockito 版本会有所帮助。
先得到Mockito-kotlin然后 在 mockito 中,当你想模拟 suspend 函数时可以使用此代码 :
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
})