如何在onChange回调中模拟Navigator.push结果、验证updateForm调用及用Mocktail模拟Location?
问题与解决方案
场景还原
你在页面中使用了如下Widget:
FormSelectedWidget( onChanged: () async { Location? result = await Navigator.pushNamed( context, RouteName.searchLocationScreen, ) as Location?; if (result != null) { context.read<MyActionCubit>().updateForm(); } } )
希望验证updateForm()方法被调用一次,但当前编写的验证代码无法正确生效:
verify( () => MyActionCubit.updateForm(), ).called(1);
正确验证updateForm()调用的方式
你当前的验证代码错误在于直接调用了类的静态方法MyActionCubit.updateForm(),但实际业务代码中调用的是MyActionCubit实例的方法。必须使用Mocktail创建MyActionCubit的模拟实例,再验证该实例的方法调用:
步骤1:创建MyActionCubit的模拟类
import 'package:mocktail/mocktail.dart'; class MockMyActionCubit extends Mock implements MyActionCubit {}
步骤2:编写完整测试用例
test('updateForm is called when Location result is not null', () async { // 创建Cubit的模拟实例 final mockCubit = MockMyActionCubit(); // 构建测试Widget树,注入模拟的Cubit final tester = await pumpWidget( BlocProvider.value( value: mockCubit, child: MaterialApp( home: Scaffold(body: FormSelectedWidget( onChanged: () async { final result = await Navigator.pushNamed( tester.context, RouteName.searchLocationScreen, ) as Location?; if (result != null) { tester.context.read<MyActionCubit>().updateForm(); } }, )), // 注册跳转目标页面(可使用空Widget占位) routes: { RouteName.searchLocationScreen: (_) => const SizedBox(), }, ), ), ); // 触发FormSelectedWidget的onChanged回调(假设通过点击触发) await tester.tap(find.byType(FormSelectedWidget)); await tester.pumpAndSettle(); // 验证模拟实例的updateForm方法被调用1次 verify(() => mockCubit.updateForm()).called(1); });
使用Mocktail模拟Location对象
完全可以用Mocktail模拟Location对象,步骤如下:
步骤1:创建Location的模拟类
class MockLocation extends Mock implements Location {}
步骤2:在测试中模拟返回值
通过Stub Navigator.pushNamed 的返回值,让它返回模拟的Location实例,确保业务代码进入非空分支:
test('updateForm is called with mocked Location', () async { final mockCubit = MockMyActionCubit(); final mockLocation = MockLocation(); // Stub Navigator.pushNamed,返回模拟的Location when(() => Navigator.pushNamed( any(), RouteName.searchLocationScreen, )).thenAnswer((_) async => mockLocation); // 后续构建Widget、触发回调、验证调用的步骤和之前一致 final tester = await pumpWidget(...); await tester.tap(find.byType(FormSelectedWidget)); await tester.pumpAndSettle(); verify(() => mockCubit.updateForm()).called(1); });
内容的提问来源于stack exchange,提问作者rifkyadniputra
相关产品推荐
相关产品推荐

