Flutter bloc_test未抛出异常:completedIntroTutorial异常捕获测试失败
问题分析
你的测试代码存在两个核心问题,导致异常捕获分支无法触发:
- Mock对象误用:你mock了
IntroCubit,但实际测试的是真实的IntroCubit实例。when(() => mockIntroCubit.completedIntroTutorial()).thenThrow(...)只会对mock实例生效,和你在act中调用的真实cubit完全无关。 - 异常触发点错误:
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(), ), ), ); } }
关键说明
- 必须mock
SharedPreferences而非IntroCubit,因为异常需要从cubit依赖的外部服务抛出,才能触发内部的try-catch逻辑。 - 确保抛出的异常类型是
Exception或其子类,你的AppError需要实现Exception接口(如果没实现的话),否则无法被on Exception catch捕获。
内容的提问来源于stack exchange,提问作者Tempelritter
相关产品推荐
相关产品推荐

