Flutter单元测试中能否验证showDialog的barrierDismissible参数设置?
如何直接测试showDialog的barrierDismissible参数是否正确传递
当然可以直接测试你是否正确传递了barrierDismissible参数,核心思路是拦截showDialog的调用并验证传入的参数值,推荐用Mockito工具实现。这种方式不需要依赖点击外部关闭的行为,直接聚焦于你的代码是否正确传参,更精准地测试实现逻辑。
方法一:通过NavigatorObserver验证路由属性
弹窗展示时会生成对应的PageRoute,我们可以通过导航观察者获取这个路由,直接检查它的barrierDismissible属性:
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; // 创建Mock类拦截导航事件 class MockNavigatorObserver extends Mock implements NavigatorObserver {} void main() { testWidgets('verify barrierDismissible is set to true when showing dialog', (tester) async { final mockObserver = MockNavigatorObserver(); // 构建测试页面,按钮点击触发弹窗 await tester.pumpWidget( MaterialApp( home: Scaffold( body: ElevatedButton( onPressed: () { showDialog( context: tester.element(find.byType(ElevatedButton)), barrierDismissible: true, // 待验证的参数 builder: (context) => const AlertDialog(key: Key('test_dialog')), ); }, child: const Text('Show Dialog'), ), ), navigatorObservers: [mockObserver], ), ); // 触发弹窗操作 await tester.tap(find.text('Show Dialog')); await tester.pumpAndSettle(); // 捕获路由并验证barrierDismissible属性 final captured = verify(mockObserver.didPush(captureAny, captureAny)).captured; final dialogRoute = captured[0] as PageRoute; expect(dialogRoute.barrierDismissible, isTrue); }); }
方法二:直接Mock showDialog函数
如果你的弹窗逻辑被封装在业务类(比如Cubit、ViewModel)中,可以直接MockshowDialog函数,验证调用时的参数:
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; // 定义showDialog的函数类型,方便Mock typedef ShowDialogFunc = Future<T?> Function<T>({ required BuildContext context, required Widget Function(BuildContext) builder, bool barrierDismissible, }); class MockShowDialog extends Mock implements ShowDialogFunc {} void main() { testWidgets('verify barrierDismissible is passed as true', (tester) async { final mockShowDialog = MockShowDialog(); // 拦截showDialog调用,返回空Future when(mockShowDialog( context: anyNamed('context'), builder: anyNamed('builder'), barrierDismissible: anyNamed('barrierDismissible'), )).thenAnswer((_) => Future.value(null)); // 构建测试页面,点击按钮调用Mock的showDialog await tester.pumpWidget( MaterialApp( home: Scaffold( body: ElevatedButton( onPressed: () { mockShowDialog( context: tester.element(find.byType(ElevatedButton)), builder: (context) => const AlertDialog(), barrierDismissible: true, ); }, child: const Text('Show Dialog'), ), ), ), ); await tester.tap(find.text('Show Dialog')); // 验证参数是否正确传递 verify(mockShowDialog( context: anyNamed('context'), builder: anyNamed('builder'), barrierDismissible: true, )).called(1); }); }
两种方法的适用场景
- 方法一更适合测试UI层直接调用
showDialog的场景,贴近真实的弹窗展示流程; - 方法二更适合测试封装了弹窗逻辑的业务层代码,专注于参数传递的正确性。
内容的提问来源于stack exchange,提问作者H.Rahimy
相关产品推荐
相关产品推荐

