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

Flutter bloc_test未抛出异常:completedIntroTutorial异常捕获测试失败

问题分析

你的测试代码存在两个核心问题,导致异常捕获分支无法触发:

  1. Mock对象误用:你mock了IntroCubit,但实际测试的是真实的IntroCubit实例。when(() => mockIntroCubit.completedIntroTutorial()).thenThrow(...)只会对mock实例生效,和你在act中调用的真实cubit完全无关。
  2. 异常触发点错误:completedIntroTutorial的try块里只有sharedPreferences.getBool这一个可能抛出异常的操作,你需要让这个方法抛出异常,而不是mock cubit的方法。
解决方案

1. 创建SharedPreferences的Mock类

class MockSharedPreferences extends Mock implements SharedPreferences {}

2. 修改测试初始化逻辑

替换原有的SharedPreferences实例为mock对象,并配置getBool方法抛出异常:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  late MockSharedPreferences mockSharedPreferences;
  late IntroCubit introCubit;

  setUp(() {
    mockSharedPreferences = MockSharedPreferences();
    introCubit = IntroCubit(sharedPreferences: mockSharedPreferences);
  });

  group('Intro Cubit Test', () {
    const AppError tAppError = AppError(message: 'Failed to get bool');

    blocTest<IntroCubit, IntroState>(
      'emits [IntroCubitInitial, IntroCubitLoading, IntroCubitError] when completedIntroTutorial fails',
      setUp: () => when(() => mockSharedPreferences.getBool(IntroCubit.completedIntro))
          .thenThrow(const AppError(message: 'Failed to get bool')),
      build: () => introCubit,
      act: (cubit) => cubit.completedIntroTutorial(),
      expect: () => <IntroState>[
        IntroCubitInitial(),
        IntroCubitLoading(),
        const IntroCubitError(appError: tAppError),
      ],
    );
  });
}

3. 额外优化点(可选)

你的completedIntroTutorial方法中,if和else分支逻辑完全一致,可以简化:

void completedIntroTutorial() {
  emit(IntroCubitInitial());
  emit(IntroCubitLoading());
  try {
    final bool completed = sharedPreferences.getBool(completedIntro) ?? false;
    emit(IntroCubitSuccess(boolean: completed));
  } on Exception catch (exception) {
    emit(
      IntroCubitError(
        appError: AppError(
          message: exception.toString(),
        ),
      ),
    );
  }
}

关键说明

  • 必须mockSharedPreferences而非IntroCubit,因为异常需要从cubit依赖的外部服务抛出,才能触发内部的try-catch逻辑。
  • 确保抛出的异常类型是Exception或其子类,你的AppError需要实现Exception接口(如果没实现的话),否则无法被on Exception catch捕获。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:50:22