Как проверить виджет FutureBuilder с нерешенным Future

Интересно, как я могу проверить случай, когда будущее еще не завершено в тестах виджетов флаттера?

Виджет должен показывать счетчик, пока будущее не разрешено.

Я tride этот тестовый пример:

testWidgets(
  'should show a spinner when loading',
  (WidgetTester tester) async {
    when(valueRepository.getValues())
        .thenAnswer((_) => Future.delayed(Duration(seconds: 30), () => []));
    await tester.pumpWidget(withApp(ValueListPage(
      valueRepository: valueRepository,
    )));

    await tester.pumpAndSettle(
        Duration(seconds: 10), EnginePhase.build, Duration(minutes: 1));

    expect(find.byType(CircularProgressIndicator), findsOneWidget);
  },
);

Результат: будущее решено, и ожидание не удается.

Примечание: withApp инициализирует приложение с локализацией. Из-за этого я должен позвонить tester.pumpAndSettle() ждать l10n.

2 ответа

Решение

Я нашел рабочее решение с помощью fakeAsync:

testWidgets(
  'should show a spinner when loading',
  (WidgetTester tester) async {
      when(valueRepository.getValues()).thenAnswer(
          (_) => Future.delayed(Duration(seconds: 1), () => []));
      await tester.pumpWidget(withApp(ValueListPage(
        valueRepository: valueRepository,
      )));

      await tester.pump();

      expect(find.byType(CircularProgressIndicator), findsOneWidget);
      await tester.pumpAndSettle();
      expect(find.byType(CircularProgressIndicator), findsNothing);
  },
);

Пытаться

testWidgets(
  'should show a spinner when loading',
  (WidgetTester tester) async {
    tester.runAsync(() async {
      when(valueRepository.getValues())
          .thenAnswer((_) => Future.delayed(Duration(seconds: 30), () => []));
      await tester.pumpWidget(withApp(ValueListPage(
        valueRepository: valueRepository,
      )));

      await tester.pumpAndSettle(
          Duration(seconds: 10), EnginePhase.build, Duration(minutes: 1));

      expect(find.byType(CircularProgressIndicator), findsOneWidget);
    });
  },
);

Тесты запускаются с fakeAsync по умолчанию, а некоторые асинхронные коды не работают должным образом с fakeAsync.

Попытайтесь использовать завершитель, чтобы сохранить AsyncSnapshot при ожидании. например:

testWidgets('should show a spinner when loading',(WidgetTester tester) async {

    Completer completer = Completer();
    when(valueRepository.getValues())
       .thenAnswer((_) => completer.future);
    await tester.pumpWidget(withApp(ValueListPage(
    valueRepository: valueRepository,
    )));

    expect(find.byType(CircularProgressIndicator), findsOneWidget); 
 },
);
Другие вопросы по тегам