微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 nullsafety 在 Flutter 中测试 DropdownButton?使用 <String?> 崩溃

如何解决如何使用 nullsafety 在 Flutter 中测试 DropdownButton?使用 <String?> 崩溃

在使用 Flutter_test 库对 Flutter 中的 DropdownButton 进行冒烟测试时,出现以下错误

The following _TypeError was thrown while dispatching notifications for OverlayEntry: type 'Null' is not a subtype of type 'FutureOr<_DropdownRouteResult<String?>>'

接着是发生一些递归的堆栈跟踪,重复visitChildren和_unmount数百次:

#1      TransitionRoute.dispose (package:Flutter/src/widgets/routes.dart:420:26)
#2      _RouteEntry.dispose.<anonymous closure> (package:Flutter/src/widgets/navigator.dart:3112:19)
#3      ChangeNotifier.notifyListeners (package:Flutter/src/foundation/change_notifier.dart:243:25)
#4      OverlayEntry._updateMounted (package:Flutter/src/widgets/overlay.dart:130:5)
#5      _OverlayEntryWidgetState.dispose (package:Flutter/src/widgets/overlay.dart:200:18)
#6      StatefulElement.unmount (package:Flutter/src/widgets/framework.dart:4911:11)
#7      _InactiveElements._unmount (package:Flutter/src/widgets/framework.dart:2026:13)
#8      _InactiveElements._unmount.<anonymous closure> (package:Flutter/src/widgets/framework.dart:2024:7)
#9      MultiChildRenderObjectElement.visitChildren (package:Flutter/src/widgets/framework.dart:6274:16)
#10     _InactiveElements._unmount (package:Flutter/src/widgets/framework.dart:2022:13)
#11     _InactiveElements._unmount.<anonymous closure> (package:Flutter/src/widgets/framework.dart:2024:7)
#12     ComponentElement.visitChildren (package:Flutter/src/widgets/framework.dart:4739:14)
#13     _InactiveElements._unmount (package:Flutter/src/widgets/framework.dart:2022:13)
#14     _InactiveElements._unmount.<anonymous closure> (package:Flutter/src/widgets/framework.dart:2024:7)
...
#149    ComponentElement.visitChildren (package:Flutter/src/widgets/framework.dart:4739:14)
#150    _InactiveElements._unmount (package:Flutter/src/widgets/framework.dart:2022:13)
#150    ComponentElement.visitChildren (package:Flutter/src/widgets/framework.dart:4739:14)
#151    _InactiveElements._unmount (package:Flutter/src/widgets/framework.dart:2022:13)
#161    ListIterable.forEach (dart:_internal/iterable.dart:39:13)
#162    _InactiveElements._unmountAll (package:Flutter/src/widgets/framework.dart:2035:25)
#163    BuildOwner.finalizeTree.<anonymous closure> (package:Flutter/src/widgets/framework.dart:2869:27)
#164    BuildOwner.lockState (package:Flutter/src/widgets/framework.dart:2669:15)
#165    BuildOwner.finalizeTree (package:Flutter/src/widgets/framework.dart:2868:7)
#166    AutomatedTestWidgetsFlutterBinding.drawFrame (package:Flutter_test/src/binding.dart:1130:19)
#167    RendererBinding._handlePersistentFrameCallback (package:Flutter/src/rendering/binding.dart:320:5)
#168    SchedulerBinding._invokeFrameCallback (package:Flutter/src/scheduler/binding.dart:1119:15)
#169    SchedulerBinding.handleDrawFrame (package:Flutter/src/scheduler/binding.dart:1057:9)
#170    AutomatedTestWidgetsFlutterBinding.scheduleWarmUpFrame (package:Flutter_test/src/binding.dart:1056:5)
#171    runApp (package:Flutter/src/widgets/binding.dart:1049:7)
#172    TestWidgetsFlutterBinding._runTestBody (package:Flutter_test/src/binding.dart:804:7)

错误仅在测试时发生,并且应用在物理设备上运行时没有任何错误

main.dart

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),),body: Center(
        child: DropdownButton<String?>(
          key: const Key('dropdownbutton'),hint: const Text('ASD'),items: const [
            DropdownMenuItem<String>(value: '1',child: Text('1')),DropdownMenuItem<String>(value: '2',child: Text('2')),],onChanged: (_) {},);
  }

widget_test.dart

final Type dropdownMenuItemType =
    DropdownMenuItem<String?>(child: Container()).runtimeType;

void main() {
  testWidgets('Tap DropdownButton makes DropdownMenuItems visible',(WidgetTester tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(MyApp());

    // expect(find.byType(dropdownMenuItemType).hitTestable(),findsnothing);

    //open dropdown menu
    await tester.tap(find.byKey(const Key('dropdownbutton')));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    // expect(find.text('1').hitTestable(),findsOneWidget);
    // expect(find.text('2').hitTestable(),findsOneWidget);
  });
}

可以通过将 main.dart 中的 DropdownButton<String?> 设置为 DropdownButton<String> 来“修复”错误。我明白 null 不能是 DropDownButton 的值,因此“?”可以删除,否则无论如何它都会崩溃。但是不明白为什么数据充足的时候就崩溃了。

最小代码示例 here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。