当使用 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 上崩溃。但是我不明白为什么当数据足够时它会崩溃。
此处的最小代码示例。