Flutter 如何模拟对 rootBundle.loadString(...) 的调用,然后重置模拟的行为?

Posted

技术标签:

【中文标题】Flutter 如何模拟对 rootBundle.loadString(...) 的调用,然后重置模拟的行为?【英文标题】:Flutter how to mock a call to rootBundle.loadString(...), then reset the mocked behavior? 【发布时间】:2020-05-21 14:16:37 【问题描述】:

在我的颤振代码中,我有这样做的逻辑:

final jsonString = await rootBundle.loadString('AssetManifest.json');

我有一些测试,我想在到达这条线时返回一个假的AssetManifest.json

为了模拟它,我在测试中这样做:

ServicesBinding.instance.defaultBinaryMessenger
    .setMockMessageHandler('flutter/assets', (message) 
  final Uint8List encoded =
      utf8.encoder.convert('"Foo.ttf":["Foo.ttf"]');
  return Future.value(encoded.buffer.asByteData());
);

奇怪的是,这个工作,但是在它之后运行的任何测试都会挂起(当它到达await rootBundle.loadString('AssetManifest.json') 行时,它们都会卡在代码中。

我已经尝试添加

ServicesBinding.instance.defaultBinaryMessenger
    .setMockMessageHandler('flutter/assets', null);

但这似乎并没有正确地“清理”被嘲笑的行为。事实上,如果我在 setUp 中运行上述行,运行的 first 测试会挂起。

所以我是在嘲笑这种行为错了吗?还是我没有正确清理它?

【问题讨论】:

当您说在它之后运行的测试挂起时,您是指同一组中的其他测试、同一文件中的其他测试还是其他文件中的其他测试?我注意到虽然同一组或文件中的测试共享某种程度的状态,但将测试放在单独的文件中会完全从状态的角度隔离它们。我知道这是一种解决方法而不是解决方案,但也许它可以帮助你。 同一文件中的其他测试!有问题的测试之后的任何测试都会挂起。最后,我选择按照您的建议进行操作,将测试放在自己的文件中。 【参考方案1】:

我遇到了同样的问题,并认为这是由于捆绑包缓存造成的。这将导致上述测试失败,因为消息永远不会被发送。调用loadString时,可以指定是否缓存结果。例如。 loadString('AssetManifest.json', false).

请注意,如果您使用loadStructuredData,实现可以缓存结果并且您不能告诉它不缓存。

【讨论】:

以上是关于Flutter 如何模拟对 rootBundle.loadString(...) 的调用,然后重置模拟的行为?的主要内容,如果未能解决你的问题,请参考以下文章

从main()调用await rootBundle.loadString(…)时,Flutter应用程序挂起

为啥我在 Flutter 测试期间使用 rootBundle.load 得到“对空值使用空检查运算符”?

如何在主方法 Flutter 中加载 json?

在颤振单元测试中访问 rootBundle

Flutter:如何在不阻塞 UI 的情况下异步地从资产中读取文件

如何更改 Flutter 中的 ios 模拟器?