You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter使用blocTest测试Cubit时actual返回空数组问题排查

错误原因
  1. blocTest的build回调没有返回全新的Cubit实例
    blocTest内部需要自行管理被测试实例的生命周期、订阅状态流,你直接传入setUp中初始化的外部cubit实例,会导致blocTest无法正常订阅状态变更,所以收不到任何emit的状态,返回空数组。
  2. 预期值生成时机错误
    expect回调的执行时机早于act回调,你在expect中读取cubit.state.scrollValue拿到的是初始值0.0,和实际emit的scrollValue: 49不匹配,本身预期值就是错误的。
  3. 重复状态被自动过滤
    你在act中先后调用updateCloseContainer和handleClosingContainer,两个方法最终生成的状态完全相同(isClosed都是false,scrollValue都是49),基于Equatable的状态对比逻辑,bloc会默认过滤掉和上一次完全相同的状态,不会触发第二次emit。

修正后的测试代码
void main() {
  group('CloseContainerCubit', () {
    test(
        'the initial state for the CloseContainerCubit is that cubit is not closed and scrollValue is 0)',
        () {
      final cubit = CloseContainerCubit();
      expect(
          cubit.state, CloseContainerState(isClosed: false, scrollValue: .0));
      cubit.close();
    });

    blocTest<CloseContainerCubit, CloseContainerState>(
      'the cubit should emit a CloseContainerState(isClosed: false) ' 
      'when cubit.updateCloseContainer(scroll) is called '
      'and scroll < SCROLL_CLOSE_VALUE',
      build: () => CloseContainerCubit(), // 直接返回新实例,不要引用外部变量
      act: (bloc) {
        bloc.updateCloseContainer(SCROLL_CLOSE_VALUE - 1);
        bloc.handleClosingContainer();
      },
      expect: () => <CloseContainerState>[
        // 直接写明确的预期值,不要读取实例状态
        CloseContainerState(isClosed: false, scrollValue: SCROLL_CLOSE_VALUE -1)
      ],
    );
  });
}

扩展说明:如果测试滚动值大于阈值的场景,比如传入SCROLL_CLOSE_VALUE +1,那么handleClosingContainer会生成不同的状态,此时expect需要包含两个状态:

expect: () => <CloseContainerState>[
  CloseContainerState(isClosed: false, scrollValue: SCROLL_CLOSE_VALUE +1),
  CloseContainerState(isClosed: true, scrollValue: SCROLL_CLOSE_VALUE +1),
],

内容的提问来源于stack exchange,提问作者Marcel Iwanicki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 05:48:03