如何使用 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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...