Как протестировать приложение Flutter, в котором в initState () выполняется асинхронный вызов? - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть StatefulWidget, который выполняет асинхронный вызов в initState() для создания виджета.Когда я запускаю это вручную, виджет действительно быстро собирается.

Однако в моем тесте, даже если я использую await tester.pump() или await tester.pumpAndSettle(), виджет, кажется, не создается, пока послеИспытание выполнено.

Код виджета:

Widget _coolWidget;

@override
void initState() {
  super.initState();
  _coolWidget = Container(); // If I set this to OverflowBox() my test passes
  _buildWidgetFromCanvas();
}

Future<void> _buildWidgetFromCanvas() {
  final ui.PictureRecorder recorder = ui.PictureRecorder();
  final ui.Canvas canvas = ui.Canvas(recorder);
  // ... more canvas drawing code ...
  final img = ... // Image.memory() I build from the canvas
  if (!mounted) {
    print('no longer mounted');
    return;
  }

  setState(() {
    print(img);
    _coolWidget = OverflowBox(
      child: img,
    );
    print(_coolWidget);
  });
}

Код теста:

void main() {
  testWidgets('''OverflowBox shows up.''', (WidgetTester tester) async {
    await _setUp(tester); // Just instantiates my widget in an app
    await tester.pumpAndSettle();
    expect(find.byType(OverflowBox).evaluate().length, 1);
  });
}

Вывод при запуске результатов теста в:

failed: Error caught by Flutter test framework, thrown running a test.
Expected: <1>
Actual: <0>

Но если я установлю _coolWidget = OverflowBox(); в initState(), тест пройден.

У меня есть другие тесты, которые запускаются после этого.После того, как они будут сделаны, я вижу, как печать регистрирует print(img); и print(_coolWidget); сверху, и она правильно записывает нарисованное изображение.

Я также получаю печать no longer mounted, но это происходит только каксамый последний отпечаток, до встроенного в Flutter (tearDownAll).

Установка длительностей в pump () и pumpAndSettle (), похоже, ничего не меняет.

Я, вероятно, отсутствуетчто-то очевидное.

1 Ответ

0 голосов
/ 11 февраля 2019

Подумайте об использовании FutureBuilder, если ваш метод build основан на асинхронной работе.


Future<Image> _buildWidgetFromCanvas() {
  final ui.PictureRecorder recorder = ui.PictureRecorder();
  final ui.Canvas canvas = ui.Canvas(recorder);
  // ... more canvas drawing code ...
  if (!mounted) {
    return null
  }
  final img = ... // Image.memory() I build from the canvas
  return img;
}

FutureBuilder<Image>(
  future: _buildWidgetFromCanvas, // a previously-obtained Future<Image> or null
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
      case ConnectionState.active:
      case ConnectionState.waiting:
        return SizedBox(height: <height>, width: <width>);
      case ConnectionState.done:
        return OverflowBox(child: snapshot.data);
    }
    return null; // unreachable
  },
)

Вы также можете обновить свой тестовый код следующим образом:

  expect(find.byType(OverflowBox), findsOneWidget);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...