Flutter widget测试中如何关联Mock的GetXController完成测试
解决方案
核心逻辑说明
你当前的实现思路是正确的,问题出在没有将Mock控制器注册到GetX的依赖容器中,导致LoginView内部Get.put默认创建了真实的LoginViewController实例,和你声明的Mock实例没有关联。你不需要依赖get_test包,直接用GetX自带的依赖管理API即可完成空安全下的注入替换。
具体实现步骤
1. 完善Mock控制器的实现
你需要在Mock类中模拟真实控制器的可观测属性和方法行为,保证值变化时可以通知UI更新:
class MockLoginViewController extends Mock implements LoginViewController { // 模拟真实控制器的可观测布尔值 final _mockCanCheckBiometrics = false.obs; @override Rx<bool> get canCheckBiometrics => _mockCanCheckBiometrics; @override void setBiometrics(bool newValue) { _mockCanCheckBiometrics.value = newValue; } }
2. 调整测试的初始化和销毁逻辑
在每个测试运行前提前将Mock控制器注入GetX容器,测试结束后清空容器避免用例之间互相干扰:
void main(){ late MockLoginViewController mockController; setUp(() { // 强制清空已存在的同类型控制器,避免残留影响 Get.delete<LoginViewController>(force: true); mockController = MockLoginViewController(); // 提前注入Mock控制器,优先级高于LoginView内部的Get.put Get.put<LoginViewController>(mockController, permanent: true); }); tearDown(() { // 清空所有GetX注册的依赖,重置环境 Get.reset(); });
3. 编写测试用例
拆分两种场景的测试,修改Mock控制器的值后等待UI更新再做断言:
group('Controls are present and functioning', () { // ... 其他测试 testWidgets('生物识别支持时开关正常展示', (tester) async { await tester.pumpWidget(const _LoginWrapper()); // 修改Mock控制器的生物识别状态 mockController.setBiometrics(true); // 等待UI渲染完成 await tester.pumpAndSettle(); expect(find.byKey(UIKeys.keySwitchBiometrics), findsOneWidget); }); testWidgets('生物识别不支持时开关正常隐藏', (tester) async { await tester.pumpWidget(const _LoginWrapper()); mockController.setBiometrics(false); await tester.pumpAndSettle(); expect(find.byKey(UIKeys.keySwitchBiometrics), findsNothing); }); }); } class _LoginWrapper extends StatelessWidget { const _LoginWrapper({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp(home: LoginView()); } }
补充说明
如果你需要额外验证LoginView启动时确实调用了local_auth的检测逻辑并正确触发setBiometrics方法,可以单独对local_auth做Mock,验证方法调用的交互即可。
内容的提问来源于stack exchange,提问作者Pheepster
相关产品推荐
相关产品推荐

