Тест виджета Flutter ожидание анимации

#animation #widget #widget-test-flutter

#Анимация #виджет #виджет-тест-flutter

Вопрос:

У меня есть тест виджета, похожий на:

 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 миллисекунд, и, как вы можете видеть, продолжительность накачки удваивается.

Комментарии:

1. Вы узнали, каков был ответ?

2. @SilkeNL еще нет

3. Вы пробовали перекачку без продолжительности? await tester.tap(find.byType(MyWidget)); await tester.pump(new Duration(milliseconds: 3000));

4. У меня была похожая проблема, когда я не мог найти виджет после AnimationController.forward вызова. Я «исправил» это, назначив a ValueKey виджету, который я хочу протестировать, а затем используя этот ключ для проверки информации. Однако это не решение проблемы, а скорее хак.

5. Привет @notarealgreal вы все еще не нашли никакого решения для этого?

Ответ №1:

Вместо await tester.pump(new Duration(milliseconds: 3000)); попытки ожидания tester.pumpAndSettle();

этот тип перекачки ожидает окончания анимации, а затем перекачивает кадры.

Ответ №2:

У меня была такая же проблема, и вот что происходило.

Когда вы сделаете

 await animationController.forward();
 

Вы не ожидаете простого Future<void> завершения, а TickerFuture (расширяется Future<void> ).

По какой-то причине в моих тестах некоторые TickerFuture s из animationController.forward() weere отменены.

В документе TickerProvider говорится:

Если тикер удален без остановки или если он остановлен с отмененным значением true, то это будущее никогда не завершится.

Этот класс работает как обычный Future, но имеет дополнительное свойство orCancel, которое возвращает производное Future, которое завершается с ошибкой, если тикер, который вернул TickerFuture, был остановлен с cancelled, установленным в true, или если он был удален без остановки.

Чтобы выполнить обратный вызов, когда либо это будущее разрешится, либо когда тикер отменен, используйте 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.