间谍 Mockito 与协程

huangapple go评论73阅读模式
英文:

spy Mockito with Coroutines

问题

以下是您提供的内容的翻译部分:

我有一个名为 ViewModel 的类

当变量 shouldCheck 改变时会调用函数 open

    class ViewModel {
    
        val shouldCheck = MutableLiveData<Boolean>()
        
        val check by lazy {
            shouldCheck.switchMap {
                liveData(Dispatchers.IO) {
                    open()
                    emit(true)
                }
            }
        }
    
        fun open(){
            println("我是开放的")
        }
        
    }

我创建了一个简单的测试但验证 open 函数失败了

    @ExperimentalCoroutinesApi
    class CoroutineTestRule(private val dispatcher: CoroutineDispatcher = TestCoroutineDispatcher()) : TestWatcher() {
    
        override fun starting(description: Description?) {
            super.starting(description)
            Dispatchers.setMain(dispatcher)
        }
    
        override fun finished(description: Description?) {
            super.finished(description)
            Dispatchers.resetMain()
        }
    
    }


        @get:Rule
        val coroutineScope = CoroutineTestRule()

        @Before
        fun setUp() {
            viewModel = spy(ViewModel())
        }
        @Test
        fun checkTest() =  runBlocking {
        
            // 观察
            viewModel.check.observeForever {
                // ...
            }
        
            // 动作
            viewModel.shouldCheck.value = true
        
            // 预期
            verify(viewModel, times(1)).open()
        
        }

在调试模式下我检查了一下函数 open 被调用了并打印出 "我是开放的"但我遇到了这个错误

    Wanted but not invoked:
    viewModel.open(); 
    However, there were exactly 2 interactions with this mock:


如果我移除 switchMap 和 `liveData(Dispatchers.IO)`,测试就会通过但我需要保留它
英文:

I have a class with the name ViewModel.

When the variable shouldCheck change, the function open is called.

class ViewModel {

    val shouldCheck = MutableLiveData&lt;Boolean&gt;()
    
    val check by lazy {
        shouldCheck.switchMap {
            liveData(Dispatchers.IO) {
                open()
                emit(true)
            }
        }
    }

    fun open(){
        println(&quot;I am open&quot;)
    }
    
}

I create a simple test. but verify function open is failed

@ExperimentalCoroutinesApi
class CoroutineTestRule(private val dispatcher: CoroutineDispatcher = TestCoroutineDispatcher()) : TestWatcher() {

    override fun starting(description: Description?) {
        super.starting(description)
        Dispatchers.setMain(dispatcher)
    }

    override fun finished(description: Description?) {
        super.finished(description)
        Dispatchers.resetMain()
    }

}


    @get:Rule
    val coroutineScope = CoroutineTestRule()

    @Before
    fun setUp() {
        viewModel = spy(ViewModel())
    }
    @Test
    fun checkTest() =  runBlocking {
    
        // observe
        viewModel.check.observeForever {
            // ...
        }
    
        // Action
        viewModel.shouldCheck.value = true
    
        // Expected
        verify(viewModel, times(1)).open()
    
    }

in debug mode, I checked that and function open is called.and print &quot;I am open&quot;, but I have this error.

Wanted but not invoked:
viewModel.open(); 
However, there were exactly 2 interactions with this mock:

if I remove switchMap and liveData(Dispatchers.IO) test passed.
but I need it there.

答案1

得分: 0

根据谷歌:

我的建议是像这样注入调度程序:

class MyViewModel(private val ioDispatcher: CoroutineDispatcher)

在测试中使用 TestCoroutineDispatcher,这可能会有所帮助。

英文:

According to Google:

间谍 Mockito 与协程

My advice would be to inject the dispatcher like this:

class MyViewModel(private val ioDispatcher: CoroutineDispatcher)

And use the TestCoroutineDispatcher within your tests, this might help

huangapple
  • 本文由 发表于 2020年10月19日 23:54:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/64430931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定