Android Mockito Kotlin 协程测试取消

标签 android kotlin mockito kotlin-coroutines mockito-kotlin

我有 retrofit 服务

interface Service {
    @PUT("path")
    suspend fun dostuff(@Body body: String)
}

它用于android View 模型。

class VM : ViewModel(private val service: Service){
   private val viewModelJob = Job()
   private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

   val state = MutableLiveData<String()

   init {
      uiScope.launch { 
         service.doStuff()
         state.value = "lol"
      }
   }

   override fun onCleared(){
      viewModelJob.cancel()
   }
}

我想编写一个取消 View 模型的测试。这将通过模拟服务并延迟来完成,以便 co 例程无法完成。在阻塞时,我们调用 onCleared 来取消 co 例程。这应该可以防止状态被设置...

@Test
fun `on cleared - cancels request`() = runBlocking {
    //given
    `when`(service.doStuff()).thenAnswer { launch { delay(1000) } }

    val vm = ViewModel(service)
    // when
    vm.cleared()

    //then
    assertThat(vm.state, nullValue())
}

但是 vm.state 似乎总是被设置???清除 co 例程被取消的范围时测试的最佳方法是什么?

最佳答案

这里的问题出在 thenAnswer { launch { delay(1000) } } 中,它实际上使您的 doStuff 方法看起来像这样:

suspend fun doStuff() {
  launch { delay(1000) } 
}

正如你所看到的,这个函数实际上并没有挂起,它启动了一个协程并立即返回。这里实际起作用的是 thenAnswer {delay(1000) },它不起作用,因为 Mockito 中没有 thenAnswer 的挂起版本(据我所知,至少)。

我建议切换到 Mokk模拟库,原生支持 kotlin。然后你可以编写coEvery { doStuff() } coAnswers {delay(1000) },它将使你的测试通过(在修复了c的所有语法错误之后)。

关于Android Mockito Kotlin 协程测试取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57878466/

相关文章:

android - 使用 Kotlin 从相机/画廊捕获图像并在 Activity/fragment 中显示

java - 如何使用私有(private)方法调用 Mockito.given

android - 网格中的 CardView 不在所有侧面显示阴影

android - 当我们扩展它时,BaseAdapter 是如何工作的?

iphone - 如何在android中制作iphone风格的菜单栏

java - 如何在生产中使用 CDI 测试类时注入(inject)模拟

mockito - Spring 批处理作业的端到端测试用例

android - WebView getScrollY() 总是返回 0

Kotlin 标准函数 : run, with、let、also 和 apply

android - Google的SupportMapFragment MapView从另一个Fragment弹出后性能低下