6

我有一个小部件,当单击它时,它会保存一个 ID 号,覆盖一个 CircularProgressIndicator 1000 毫秒,然后弹出进度指示器并将用户路由到另一个页面。

ProgressIndicator 和 Timer 的这一位是新的,并且破坏了我的单元测试,现在给我以下错误:

The following assertion was thrown running a test:
'package:flutter_test/src/binding.dart': Failed assertion: line 574 pos 12: '() {
      'A Timer is still pending even after the widget tree was disposed.';
      return _fakeAsync.nonPeriodicTimerCount == 0;
    }': is not true.

Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new

When the exception was thrown, this was the stack:
#2      AutomatedTestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:574:12)
#3      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:415:7)
<asynchronous suspension>
#7      TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:392:14)
#8      AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:549:24)
#14     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:547:16)
#15     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:54:50)
#16     Declarer.test.<anonymous closure>.<anonymous closure> (package:test/src/backend/declarer.dart:131:19)
<asynchronous suspension>
#17     Invoker.waitForOutstandingCallbacks.<anonymous closure>.<anonymous closure> (package:test/src/backend/invoker.dart:200:17)
<asynchronous suspension>
#22     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test/src/backend/invoker.dart:197:7)
#26     Invoker.waitForOutstandingCallbacks (package:test/src/backend/invoker.dart:196:5)
#27     Declarer.test.<anonymous closure> (package:test/src/backend/declarer.dart:129:29)
<asynchronous suspension>
#28     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test/src/backend/invoker.dart:322:23)
<asynchronous suspension>
#43     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:385)
#44     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:414)
#45     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)
(elided 31 frames from class _AssertionError, class _FakeAsync, package dart:async, package
dart:async-patch, and package stack_trace)

这是损坏的测试的样子:

testWidgets('Tapping item saves its id', (WidgetTester tester) async {
  await launchApp(item, tester);
  await tester.tap(find.byConfig(item));

  expect(sameId(global_state.currentId, item.id), isTrue);
});

有没有办法在处理小部件树之前引入延迟?我还有哪些其他选择?还是我对问题的根本原因有误?

4

3 回答 3

13

testWidgets 自动引入了一个 FakeAsync 区域,可以让您逐步了解时间。用来pump提前时间。

但是,您看到的错误是因为您的小部件在处置时没有取消计时器。dispose确保您的 Widget 对象从不分配资源(如计时器),并且您的 State 对象始终在其方法中清理它们分配的任何资源。

于 2017-02-24T22:36:35.620 回答
1

您应该能够在 Quiver 的 FakeAsync 库中的 FakeAsync 中执行此操作: https ://www.dartdocs.org/documentation/quiver/0.24.0/quiver.testing.async/FakeAsync-class.html

在 Flutter 框架本身的测试中有很多这种模式的例子: https ://github.com/flutter/flutter/search?utf8=%E2%9C%93&q=FakeAsync

于 2017-02-24T22:14:58.160 回答
0

使用await tester.pumpAndSettle(),默认情况下它使用 100 毫秒延迟,但您可以添加自己的值:await tester.pumpAndSettle(const Duration(seconds:1))

如果您测试使用 Timer 的小部件或引擎盖下的一些动画小部件,它会很有用。

这是一个如何使用它的小例子:

testWidgets('build with $state state', (tester) async {
        when(() => bloc.state).thenReturn(state);
        await blocTester.test(
          tester: tester,
          stateConfig: states[state]!,
        );
        await tester.pumpAndSettle();
      })
于 2021-07-05T13:30:02.963 回答