mardi 27 novembre 2018

How to test Flutter app where there is an async call in initState()?

I have a StatefulWidget that does an async call in its initState(), to build a Widget. When I manually run this, the widget does build quickly.

However, in my test, even if I use await tester.pump() or await tester.pumpAndSettle(), the widget doesn't seem to get built, until way after the test has run.

Widget code:

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);
  });
}

Test code:

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);
  });
}

An output when I run my test results in:

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

But if I set _coolWidget = OverflowBox(); in initState(), the test passes.

I have other tests that run after this one. After those ones are done, I see the print logging the print(img); and print(_coolWidget); from above, and it correctly logs the drawn image.

I also get the no longer mounted print, but that only happens as the very last print, prior to Flutter's built in (tearDownAll).

Setting durations in the pump() and pumpAndSettle() don't seem to change anything.

I'm probably missing something obvious.

1 commentaire:

  1. https://cogitas.net/flutter-widget-tests-practical-example/ seems to use

    await tester.pump(Duration.zero);

    maybe that would have helped?

    RépondreSupprimer