3

我有一个类似的小部件测试:

testWidgets('Widget test', (WidgetTester tester) async {
  provideMockedNetworkImages(() async {
    final widget = MyWidget();

    await WidgetTestFunctions.pumpWidgetTest(
      tester,
      widget,
    );

    // ....

    await tester.tap(find.byType(MyWidget));
    await tester.pump(new Duration(milliseconds: 3000));

    // ....

    expect(widget.value, myValue);
  });
});

以及小部件的 on-tap 方法的以下实现:

_onButtonPressed() async {      
  await animationController.forward();
  setState(() {
    // ...
    // Calls method that changes the widget value.
  });           
}

我遇到的问题是,在animationController.forward()测试中调用该方法后,该setState部分未执行。我应该如何等待此方法正确完成?在应用程序运行时,这部分代码被正确调用。

似乎await tester.pump(new Duration(milliseconds: 3000));无法正常工作,动画的持续时间为 1500 毫秒,您可以看到泵的持续时间是双倍的。

4

2 回答 2

1

我有同样的问题,这就是发生的事情。

当你这样做

await animationController.forward();

你不是在等待一个简单Future<void>的完成,而是一个TickerFuture(扩展Future<void>)。

出于某种原因,在我的测试中,一些TickerFuture来自animationController.forward()weere的s被取消了。

在 的文档中TickerProvider,它说:

如果 Ticker 在没有停止的情况下被释放,或者如果它在 cancelled 设置为 true 的情况下停止,那么这个 Future 将永远不会完成。

这个类像普通的 Future 一样工作,但有一个额外的属性 orCancel,如果返回 TickerFuture 的 Ticker 在取消设置为 true 的情况下停止,或者如果它在没有停止的情况下被处置,则该类返回一个衍生的 Future,并以错误完成。

要在此未来解决或代码被取消时运行回调,请使用 whenCompleteOrCancel。

现在,问题whenCompleteOrCancel在于它会返回void(而不是Future<void>我们不能等待它。

所以这就是我所做的(受实施的启发whenCompleteOrCancel):

Future<void> thunk(dynamic value) {
  return;
}
final TickerFuture ticker = animationController.forward();
await ticker.onCancel.then(thunk, onError: thunk); // <- This resolves even if the ticker is canceled and the tests are not stuck anymore.
于 2021-11-11T15:50:03.030 回答
1

而不是await tester.pump(new Duration(milliseconds: 3000)); 尝试等待tester.pumpAndSettle();

这种类型的泵等待动画结束,然后泵帧。

于 2021-11-22T14:48:10.077 回答