1

当使用 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)

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

主要.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);
  });
}

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

此处的最小代码示例。

4

0 回答 0