asynchronous - 如何在 initState() 中有异步调用的情况下测试 Flutter 应用程序?

标签 asynchronous testing dart flutter

我有一个 StatefulWidget,它在其 initState() 中执行异步调用,以构建一个 Widget。当我手动运行它时,小部件确实会快速构建。

但是,在我的测试中,即使我使用 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>

但如果我在 initState() 中设置 _coolWidget = OverflowBox();,测试就会通过。

我还有其他测试在此之后运行。这些完成后,我看到打印记录了 print(img);print(_coolWidget); 从上面,它正确地记录了绘制的图像。

我还得到了 no longer mounted 打印,但这只是最后一次打印,在 Flutter 内置 (tearDownAll) 之前。

在 pump() 和 pumpAndSettle() 中设置持续时间似乎没有任何改变。

我可能遗漏了一些明显的东西。

最佳答案

如果您的build 方法依赖于异步工作,请考虑使用FutureBuilder


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

关于asynchronous - 如何在 initState() 中有异步调用的情况下测试 Flutter 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53511473/

相关文章:

flutter - 如何为 flutter web 更新 pub 包 webdev

java - 如何在服务层的 PlayFramework 2 中进行异步调用?

reactjs - 如何使用 Jest 测试异步组件?

c# - 使用Xamarin Android,如何在任务完成之前显示进度条?

android - 是否可以像在旧版 Android 操作系统上一样运行我的应用程序?

testing - 缺少 else 的分支覆盖

flutter - flutter 中的计时器控制

flutter - 使 Flutter Web Sentry 错误报告可读?

C# 异步调用(本例中为 ASMX WebServices)

objective-c - UITableView - 在不阻塞主线程的情况下从 NSBundle 加载大型 UIImages