首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用StateFlow测试Android StateFlow,该mapsLatest来自另一个StateFlow,但mapLatest从未触发

用StateFlow测试Android StateFlow,该mapsLatest来自另一个StateFlow,但mapLatest从未触发
EN

Stack Overflow用户
提问于 2022-06-24 16:06:15
回答 1查看 301关注 0票数 2

所以我有一个ViewModel,我正在尝试单元测试。它使用的是stateIn运算符。我找到了关于如何测试使用stateIn操作符https://developer.android.com/kotlin/flow/test创建的状态流的文档,但是即使我正在收集流,mapLatest也不会触发。

代码语言:javascript
复制
class DeviceConfigurationViewModel(
    val systemDetails: SystemDetails,
    val step: AddDeviceStep.ConfigureDeviceStep,
    val service: DeviceRemoteService
) : ViewModel(), DeviceConfigurationModel {

    @OptIn(ExperimentalCoroutinesApi::class)
    private val _state: StateFlow<DeviceConfigurationModel.State> =
        service.state
            .mapLatest { state ->
                when (state) {
                    DeviceRemoteService.State.Connecting -> {
                        DeviceConfigurationModel.State.Connecting
                    }
                    is DeviceRemoteService.State.ConnectedState.Connected -> {
                        state.sendCommand(step.toCommand(systemDetails))
                        DeviceConfigurationModel.State.Connected
                    }
                    is DeviceRemoteService.State.ConnectedState.CommandSent -> {
                        DeviceConfigurationModel.State.Configuring
                    }
                    is DeviceRemoteService.State.ConnectedState.MessageReceived -> {
                        transformMessage(state)
                    }
                    is DeviceRemoteService.State.Disconnected -> {
                        transformDisconnected(state)
                    }
                }
            }
            .distinctUntilChanged()
            .stateIn(
                viewModelScope,
                SharingStarted.WhileSubscribed(5000), // Keep it alive for a bit if the app is backgrounded
                DeviceConfigurationModel.State.Disconnected
            )

    override val state: StateFlow<DeviceConfigurationModel.State>
        get() = _state

    private fun transformDisconnected(
        state: DeviceRemoteService.State.Disconnected
    ): DeviceConfigurationModel.State {
        return if (state.hasCause) {
            DeviceConfigurationModel.State.UnableToConnect(state)
        } else {
            state.connect()
            DeviceConfigurationModel.State.Connecting
        }
    }

    private fun transformMessage(state: DeviceRemoteService.State.ConnectedState.MessageReceived): DeviceConfigurationModel.State {
        return when (val message = state.message) {
            is Message.AddedToProject -> DeviceConfigurationModel.State.Configured
            is Message.ConfigWifiMessage -> {
                if (!message.values.success) {
                    DeviceConfigurationModel.State.Error(
                        message.values.errorCode,
                        state,
                        step.toCommand(systemDetails)
                    )
                } else {
                    DeviceConfigurationModel.State.Configuring
                }
            }
        }
    }

}

这是我的单元测试。即使我正在收集流量,mapLatest似乎也不会被触发。我正在使用这里的建议,https://developer.android.com/kotlin/flow/test

代码语言:javascript
复制
@OptIn(ExperimentalCoroutinesApi::class)
class DeviceConfigurationViewModelTest {

    private val disconnectedService = mock<DisconnectedService>()

    private val deviceServiceState: MutableStateFlow<DeviceRemoteService.State> =
        MutableStateFlow(DeviceRemoteService.State.Disconnected(disconnectedService, Exception()))

    private val deviceService = mock<DeviceRemoteService> {
        on { state } doReturn deviceServiceState
    }

    private val systemDetails = mock<SystemDetails> {

        on { controllerAddress } doReturn "192.168.1.112"

        on { controllerName } doReturn "000FFF962FE7"

    }

    private val step = AddDeviceDeviceStep.ConfigureDeviceStep(
        44,
        "Thou Shalt Not Covet Thy Neighbor’s Wifi",
        "testing616"
    )

    private lateinit var viewModel: DeviceConfigurationViewModel

    @Before
    fun setup() {
        viewModel = DeviceConfigurationViewModel(systemDetails, step, deviceService)
    }

    @Test
    fun testDeviceServiceDisconnectWithCauseMapsToUnableToConnect() =
        runTest {

            val collectJob = launch(UnconfinedTestDispatcher()) { viewModel.state.collect() }

            deviceServiceState.emit(
                DeviceRemoteService.State.Disconnected(Exception("Something bad happened"))
            )

            assertThat(viewModel.state.value).isInstanceOf(DeviceConfigurationModel.State.UnableToConnect::class.java)
            collectJob.cancel()
        }

}
EN

回答 1

Stack Overflow用户

发布于 2022-10-13 23:29:31

我认为这是因为viewModelScope在引擎盖下使用了硬编码的主调度程序。

您可以按照在Android文档中的说明来查看如何设置测试的主调度程序。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72746719

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档