8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

使用 Dispatchers.Main.immediate(或 viewModelScope)更改 StateFlow 的值时,Flow 不会在测试中发出

scibuff 2月前

23 0

我调查了几个小时并搜索了网络(甚至打扰了 ChatGPT),但我很困惑这个问题还没有得到解决(显然我的知识非常有限)。所以这是设置:我有一个视图...

我调查了几个小时并搜索了网络(甚至打扰了 ChatGPT),但我很困惑,就我(显然非常有限的)知识而言,这个问题还没有得到解决。

因此,设置如下:我有一个带有 的视图模型, StateFlow 该模型在一个块内更新 launch { ... } 。在测试代码中,我无法让流程发出任何内容(初始值除外)。只有当我在生产代码中放置 yield() delay() 调用时,它才会正确发出。

我将示例简化为其本质以重现该问题(只需复制粘贴即可运行):

@ExperimentalCoroutinesApi
class MyTest {

    class MyViewModel {

        private val _state = MutableStateFlow(false)
        val state = _state.asStateFlow()

        fun doSomething(runYield: Boolean) {
            val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) // btw. this is how Android provides a `viewModelScope`
            viewModelScope.launch {
                _state.value = true
                // some workload here
                if (runYield)
                    yield()
                _state.value = false
            }
        }
    }

    @Before
    fun setUp() {
        Dispatchers.setMain(UnconfinedTestDispatcher())
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `Failing test`() = runTestCase(runYield = false)

    @Test
    fun `Passing test`() = runTestCase(runYield = true)

    private fun runTestCase(runYield: Boolean) = runTest {
        val viewModel = MyViewModel()

        // Collect emissions to `state` in this mutable list
        val testResults = mutableListOf<Boolean>()

        // backgroundScope makes sure the job is shut down after the test
        backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
            viewModel.state.toList(testResults)
        }

        viewModel.doSomething(runYield)

        assertEquals(listOf(false, true, false), testResults)
    }
}

使用 a MutableSharedFlow 代替 the MutableStateFlow 也可以缓解该问题。

我花了很长时间才知道 yield() delay() 调用可以缓解这个问题。但是:这到底是为什么呢?如果没有它我又如何解决这个问题呢?

使用 Kotlin 版本 1.9.10 和 Coroutines 核心+测试库 1.8.1。

帖子版权声明 1、本帖标题:使用 Dispatchers.Main.immediate(或 viewModelScope)更改 StateFlow 的值时,Flow 不会在测试中发出
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由scibuff在本站《kotlin》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我有一个片段,其中我有一个 scrollview (scrollview 内的 edittext) 和 recyclerview。当我单击 edittext 时,键盘会隐藏它。我只有一个 Activity 和许多片段...

    我有一个片段,其中我有一个 scrollview (scrollview 内的 edittext) 和 recyclerview。当我单击 edittext 时,键盘会隐藏它。

    我只有一个活动和许多片段,所以我无法 android:windowSoftInputMode="adjustPan" 在清单中使用。(如果我在清单中写入,它工作正常,但它会影响所有片段,这是我不想要的)。

    在片段中我已经尝试过

    activity?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
    ) 
    

    但它不起作用。

    请有人帮帮我。

返回
作者最近主题: