Flutter `showModalBottomSheet` Ticker 在测试期间没有被处理

标签 flutter dart flutter-animation flutter-test

在编写 Flutter 小部件测试时,我遇到了一个错误,其中在 showModalBottomSheet() 期间创建的 Ticker 没有被处理掉。

我想我明白如果我要实现我自己的 Flutter 动画,我应该制作一个 AnimationController,我会调用 AnimationController.dispose()在小部件期间 dispose方法。

然而,由于(我相信) AnimationController 被抽象出来以提供一些便利,我不确定在测试完成后在哪里或如何确保小部件被处理。

注意:代码有效,当我在模拟器/模拟器上进行测试时,模态底部工作表很棒。我只想能够在 testWidgets 中测试它测试。

我看过 showModalBottomSheet 文档 https://api.flutter.dev/flutter/material/showModalBottomSheet.html但这仅显示了如何使用该功能。我没有找到任何方法来控制何时可以处理动画。

test_test.dart

(额外的 pump() 在异步问题的情况下,但它似乎没有帮助)

testWidgets('Taping edit score button brings up bottom sheet to edit',
      (WidgetTester tester) async {
    setUp();
    await tester.pumpWidget(MaterialApp(
      home: GameList(
        game: Game(players: players),
      ),
    ));
    await tester.tap(find.byKey(Key('p1-edit-score')));
    await tester.pump();
    await tester.pump();
    expect(find.byKey(Key('test')), findsOneWidget);
    await tester.tap(find.byKey(Key('tap-me')));
    await tester.pump();
    await tester.pump();
    tearDown();
  });

game_view.dart


class GameView extends StatefulWidget {
  GameView({@required this.playerList, @required this.onResetPlayerScores});

  final Function onResetPlayerScores;
  final List<Player> playerList;

  @override
  _GameState createState() => _GameState();
}

class _GameState extends State<GameView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(...),
      body: GameList(
        game: Game(players: widget.playerList),
      ),
    );
  }
}


game_list.dart

为简洁起见去掉了一些小部件

class GameList extends StatefulWidget {
  GameList({@required this.game});

  final Game game;

  @override
  GameListState createState() => GameListState(game: game);
}

class GameListState extends State<GameList> {
  GameListState({@required this.game});

  final Game game;

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      shrinkWrap: true,
      itemCount: game.players.length,
      itemBuilder: (BuildContext context, int index) {
        return Card(
          child: Column(
            children: <Widget>[
              ListTile(
                trailing: Text(
                  '${game.players[index].score.toInt()}',
                ),
                title: Text(
                  '${game.players[index].name}',
                ),
              ),
              Row(
                children: <Widget>[
                  FlatButton(
                    child: Icon(
                      Icons.edit,
                      color: Colors.grey[700],
                    ),
                    onPressed: () async {
                      _settingModalBottomSheet(context);
                    },
                    key: Key(
                      '${game.players[index].name}-edit-score',
                    ),
                  ),
                ],
              ),
            ],
          ),
        );
      },
      separatorBuilder: (BuildContext context, int index) => const Divider(),
    );
  }
}

void _settingModalBottomSheet(context) {
  showModalBottomSheet(
    context: context,
    builder: (BuildContext buildContext) {
      return Center(
        child: Container(
          child: Wrap(
            children: <Widget>[
              Text(
                'edit',
                key: Key('test'),
              ),
              ListTile(
                leading: Icon(Icons.edit),
                title: Text('Video'),
                onTap: () {
                  Navigator.pop(context, 'video');
                },
                key: Key('tap-me'),
              ),
            ],
          ),
        ),
      );
    },
  );
}
flutter test 的短输出.我认为最重要的部分。
OverlayState created a Ticker via its TickerProviderStateMixin, but at the time dispose() was called
on the mixin, that Ticker was still active. All Tickers must be disposed before calling
super.dispose(). Tickers used by AnimationControllers should be disposed by calling dispose() on the
AnimationController itself. Otherwise, the ticker will leak.
flutter test 的完整输出
The following assertion was thrown while finalizing the widget tree:
OverlayState#bfe06(tickers: tracking 1 ticker, entries: [OverlayEntry#c26ee(opaque: false;
maintainState: false), OverlayEntry#7cd4f(opaque: false; maintainState: true),
OverlayEntry#d496e(opaque: false; maintainState: false), OverlayEntry#e9ad3(opaque: false;
maintainState: true)]) was disposed with an active Ticker.
OverlayState created a Ticker via its TickerProviderStateMixin, but at the time dispose() was called
on the mixin, that Ticker was still active. All Tickers must be disposed before calling
super.dispose(). Tickers used by AnimationControllers should be disposed by calling dispose() on the
AnimationController itself. Otherwise, the ticker will leak.
The offending ticker was: _WidgetTicker(created by OverlayState#bfe06(tickers: tracking 0 tickers,
entries: [OverlayEntry#c26ee(opaque: false; maintainState: false), OverlayEntry#7cd4f(opaque: false;
maintainState: true)]))
The stack trace when the _WidgetTicker was actually created was:
#0      new Ticker.<anonymous closure> (package:flutter/src/scheduler/ticker.dart:64:40)
#1      new Ticker (package:flutter/src/scheduler/ticker.dart:66:6)
#2      new _WidgetTicker (package:flutter/src/widgets/ticker_provider.dart:225:80)
#3      _OverlayState&State&TickerProviderStateMixin.createTicker
(package:flutter/src/widgets/ticker_provider.dart:161:34)
#4      new AnimationController (package:flutter/src/animation/animation_controller.dart:245:21)
#5      BottomSheet.createAnimationController
(package:flutter/src/material/bottom_sheet.dart:128:12)
#6      _ModalBottomSheetRoute.createAnimationController
(package:flutter/src/material/bottom_sheet.dart:356:40)
#7      TransitionRoute.install (package:flutter/src/widgets/routes.dart:176:19)
#8      ModalRoute.install (package:flutter/src/widgets/routes.dart:907:11)
#9      NavigatorState.push (package:flutter/src/widgets/navigator.dart:1754:11)
#10     Navigator.push (package:flutter/src/widgets/navigator.dart:1093:34)
#11     showModalBottomSheet (package:flutter/src/material/bottom_sheet.dart:427:20)
#12     _settingModalBottomSheet (package:score_keeper/game_list.dart:98:3)
#13     GameListState.build.<anonymous closure>.<anonymous closure>
(package:score_keeper/game_list.dart:65:23)
<asynchronous suspension>
#14     _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:635:14)
#15     _InkResponseState.build.<anonymous closure>
(package:flutter/src/material/ink_well.dart:711:32)
#16     GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
#17     TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
#18     TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:312:7)
#19     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
#20
_TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding&GestureBinding.handleEvent
(package:flutter/src/gestures/binding.dart:222:20)
#21
_TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding&GestureBinding.dispatchEvent
(package:flutter/src/gestures/binding.dart:198:22)
#22     TestWidgetsFlutterBinding.dispatchEvent (package:flutter_test/src/binding.dart:365:11)
#23     WidgetTester.sendEventToBinding.<anonymous closure>
(package:flutter_test/src/widget_tester.dart:458:15)
#25     WidgetTester.sendEventToBinding.<anonymous closure>
(package:flutter_test/src/widget_tester.dart:457:39)
#28     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:41)
#29     WidgetTester.sendEventToBinding (package:flutter_test/src/widget_tester.dart:457:27)
#30     TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:422:13)
#32     TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:420:39)
#35     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:41)
#36     TestGesture.up (package:flutter_test/src/test_pointer.dart:420:27)
#37     WidgetController.tapAt.<anonymous closure> (package:flutter_test/src/controller.dart:263:21)
#51     WidgetController.startGesture (package:flutter_test/src/controller.dart)
#75     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure>
(package:flutter_test/src/binding.dart:1026:17)
#77     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure>
(package:flutter_test/src/binding.dart:1014:35)
(elided 58 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package
stack_trace)


When the exception was thrown, this was the stack:
#0      _OverlayState&State&TickerProviderStateMixin.dispose.<anonymous closure> (package:flutter/src/widgets/ticker_provider.dart:178:13)
#1      _OverlayState&State&TickerProviderStateMixin.dispose (package:flutter/src/widgets/ticker_provider.dart:191:6)
#2      StatefulElement.unmount (package:flutter/src/widgets/framework.dart:4107:12)
#3      _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1737:13)
#4      _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#5      ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#6      _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#7      _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#8      SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:5080:14)
#9      _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#10     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#11     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#12     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#13     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#14     SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:5080:14)
#15     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#16     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#17     SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:5080:14)
#18     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#19     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#20     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#21     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#22     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#23     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#24     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#25     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#26     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#27     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#28     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#29     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#30     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#31     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#32     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#33     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#34     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#35     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#36     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#37     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#38     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#39     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#40     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#41     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#42     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#43     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#44     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#45     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#46     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#47     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#48     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#49     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#50     SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:5080:14)
#51     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#52     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#53     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#54     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#55     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#56     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#57     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#58     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#59     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#60     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#61     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#62     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#63     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#64     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#65     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#66     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#67     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#68     SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:5080:14)
#69     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#70     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#71     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#72     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#73     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#74     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#75     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#76     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#77     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#78     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#79     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#80     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#81     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#82     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#83     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#84     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#85     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1735:7)
#86     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3955:14)
#87     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1733:13)
#88     ListIterable.forEach (dart:_internal/iterable.dart:39:13)
#89     _InactiveElements._unmountAll (package:flutter/src/widgets/framework.dart:1746:25)
#90     BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2426:27)
#91     BuildOwner.lockState (package:flutter/src/widgets/framework.dart:2258:15)
#92     BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2425:7)
#93     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:953:18)
#94     _TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding&GestureBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)
#95     _TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1016:15)
#96     _TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:958:9)
#97     AutomatedTestWidgetsFlutterBinding.scheduleWarmUpFrame (package:flutter_test/src/binding.dart:915:5)
#98     runApp (package:flutter/src/widgets/binding.dart:787:7)
#99     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:637:7)
<asynchronous suspension>
#102    TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:613:14)
#103    AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1010:24)
#109    AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1007:15)
#110    testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:116:22)
#111    Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:27)
<asynchronous suspension>
#112    Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:250:15)
<asynchronous suspension>
#117    Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:247:5)
#118    Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:166:33)
#123    Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:165:13)
<asynchronous suspension>
#124    Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:400:25)
<asynchronous suspension>
#138    _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
#139    _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
#140    _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)
(elided 28 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════
The following message was thrown:
An animation is still running even after the widget tree was disposed.

There was one transient callback left. The stack trace for when it was registered is as follows:
── callback 72 ──
#0      new _FrameCallbackEntry.<anonymous closure> (package:flutter/src/scheduler/binding.dart:112:33)
#1      new _FrameCallbackEntry (package:flutter/src/scheduler/binding.dart:115:6)
#2      _TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding.scheduleFrameCallback (package:flutter/src/scheduler/binding.dart:459:49)
#3      Ticker.scheduleTick (package:flutter/src/scheduler/ticker.dart:243:46)
#4      Ticker.start (package:flutter/src/scheduler/ticker.dart:159:7)
#5      AnimationController._startSimulation (package:flutter/src/animation/animation_controller.dart:685:41)
#6      AnimationController._animateToInternal (package:flutter/src/animation/animation_controller.dart:590:12)
#7      AnimationController.forward (package:flutter/src/animation/animation_controller.dart:458:12)
#8      TransitionRoute.didPush (package:flutter/src/widgets/routes.dart:188:24)
#9      ModalRoute.didPush (package:flutter/src/widgets/routes.dart:917:18)
#10     NavigatorState.push (package:flutter/src/widgets/navigator.dart:1756:11)
#11     Navigator.push (package:flutter/src/widgets/navigator.dart:1093:34)
#12     showModalBottomSheet (package:flutter/src/material/bottom_sheet.dart:427:20)
#13     _settingModalBottomSheet (package:score_keeper/game_list.dart:98:3)
#14     GameListState.build.<anonymous closure>.<anonymous closure> (package:score_keeper/game_list.dart:65:23)
<asynchronous suspension>
#15     _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:635:14)
#16     _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:711:32)
#17     GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
#18     TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
#19     TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:312:7)
#20     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
#21     _TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:222:20)
#22     _TestWidgetsFlutterBinding&BindingBase&ServicesBinding&SchedulerBinding&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
#23     TestWidgetsFlutterBinding.dispatchEvent (package:flutter_test/src/binding.dart:365:11)
#24     WidgetTester.sendEventToBinding.<anonymous closure> (package:flutter_test/src/widget_tester.dart:458:15)
#26     WidgetTester.sendEventToBinding.<anonymous closure> (package:flutter_test/src/widget_tester.dart:457:39)
#29     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:41)
#30     WidgetTester.sendEventToBinding (package:flutter_test/src/widget_tester.dart:457:27)
#31     TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:422:13)
#33     TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:420:39)
#36     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:41)
#37     TestGesture.up (package:flutter_test/src/test_pointer.dart:420:27)
#38     WidgetController.tapAt.<anonymous closure> (package:flutter_test/src/controller.dart:263:21)
#52     WidgetController.startGesture (package:flutter_test/src/controller.dart)
#76     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1026:17)
#78     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1014:35)
(elided 58 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
00:04 +25 -1: /Users/tsustare/src/projects/flutter-score-keeper/score_keeper/test/game_view_test.dart: Taping edit score button brings up bottom sheet to edit [E]
  Test failed. See exception logs above.
  The test description was: Taping edit score button brings up bottom sheet to edit```

最佳答案

尝试点击底部工作表中没有的任何可见小部件并在测试结束前触发一个框架。这将关闭底部工作表并处理它的 AnimationContoller在测试退出之前。

例如在测试结束时:

await tester.tap(find.byType(BackButtonIcon)); // any widget that isn't in the bottom sheet
await tester.pump();

关于Flutter `showModalBottomSheet` Ticker 在测试期间没有被处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57580244/

相关文章:

flutter - 动画容器 : RenderFlex overflowed by 154 pixels on the bottom

flutter - 构建 flutter 后如何设置动画?

android - 缓慢 flutter 的 GridView

java - 将 Java RSA 非对称加密转换为 Flutter Dart

dart - 如何在 dart 中将 Stream<T> 转换为 Stream<E>

flutter - 通过在列内使用堆栈,底部被无限像素溢出

flutter - 火焰组件(flutter Flame)可以作为 Flutter 应用程序中的小部件吗?

dart - 如何在 BoxDecoration 中剪辑溢出

android - Flutter - 如何在 WebView 中下载文件?

dart - 如何在 Flutter 的屏幕上获取小部件的绝对坐标?