如何为单元测试Mock SharedFlow?遇返回空流问题求助
问题原因及解决方法
核心问题
你遇到的空流问题,根源在于**MutableSharedFlow的默认行为**:
- 默认
replay = 0,意味着在没有订阅者的时候发射的值会被直接丢弃。 - 你先调用了
sharedFlow.emit(),之后才把这个流设置为xUseCase.getFlow()的返回值。当ViewModel执行collect时,之前发射的FavoriteUpdate已经丢失,所以流看起来是空的。 - 另外,
emit是挂起函数,直接在非协程环境调用会抛出异常,你的测试代码这里大概率遗漏了协程上下文(比如runBlocking)。
解决方法
方法一:让流保留历史发射值
创建MutableSharedFlow时指定replay参数为1(或更大),这样后续订阅的collector能收到之前发射的值:
val sharedFlow = MutableSharedFlow<FavoriteUpdate>(replay = 1) runBlocking { sharedFlow.emit(FavoriteUpdate(vendorCode = "x2ar", isFavorite = true, error = null)) } every { xUseCase.getFlow() } returns sharedFlow.asSharedFlow()
方法二:先订阅再发射值
先让ViewModel启动流的收集,再发射数据,确保发射时有订阅者接收:
val sharedFlow = MutableSharedFlow<FavoriteUpdate>() every { xUseCase.getFlow() } returns sharedFlow.asSharedFlow() // 先触发ViewModel的sampleFunction,开始collect流 viewModel.sampleFunction() // 在协程中发射值,此时已有订阅者 runBlocking { sharedFlow.emit(FavoriteUpdate(vendorCode = "x2ar", isFavorite = true, error = null)) }
内容的提问来源于stack exchange,提问作者Ahmet Gultekin
相关产品推荐
相关产品推荐

