几乎所有的 Flutter 插件 都包含两个部分:

  • Dart 代码,提供你的代码调用的 API。
  • 使用特定平台(或“宿主”)语言编写的代码,例如 Kotlin 或 Swift,用于实现这些 API。

事实上,原生(或宿主)语言代码区分了插件包和标准包。

构建和注册插件的宿主部分是 Flutter 应用构建过程的一部分,因此插件仅在你运行应用程序时才起作用,例如使用 flutter run 或运行 集成测试时。在运行 Dart 单元测试小部件测试时,宿主代码不可用。如果你正在测试的代码调用了任何插件,这通常会导致类似以下的错误:

MissingPluginException(No implementation found for method someMethodName on channel some_channel_name)

在单元测试使用插件的代码时,有几种选择可以避免此异常。以下解决方案按优先顺序排列。

封装插件

#

在大多数情况下,最佳方法是将插件调用封装在你自己的 API 中,并提供一种在测试中 模拟你自己的 API 的方法。

这有几个优点:

  • 如果插件 API 发生更改,你无需更新你的测试。
  • 你只测试你自己的代码,因此你的测试不会因为你使用的插件的行为而失败。
  • 你可以使用相同的方法,无论插件如何实现,甚至适用于非插件包依赖项。

模拟插件的公共 API

#

如果插件的 API 已经基于类实例,你可以直接模拟它,但需注意以下几点:

  • 如果插件使用非类函数或静态方法,则此方法无效。
  • 插件 API 更改时,测试需要更新。

模拟插件的平台接口

#

如果插件是 联邦插件,它将包含一个平台接口,允许注册其内部逻辑的实现。你可以注册该平台接口实现的模拟版本,而不是公共 API,但需注意以下几点:

  • 如果插件不是联邦插件,此方法无效。
  • 你的测试将包含插件代码的一部分,因此插件的行为可能会给你的测试带来问题。例如,如果插件作为内部缓存的一部分写入文件,你的测试行为可能会根据你是否曾运行过测试而有所不同。
  • 平台接口更改时,测试可能需要更新。

一个可能需要这样做的情况是模拟你依赖的包使用的插件的实现,而不是你自己的代码,这样你就无法更改它的调用方式。但是,如果可能,你应该改模拟使用插件的依赖项。

模拟平台通道

#

如果插件使用 平台通道,你可以使用 TestDefaultBinaryMessenger 来模拟平台通道。仅当由于某种原因上述方法均不可用时才应使用此方法,因为它存在多个缺点:

  • 只能模拟使用平台通道的实现。这意味着,如果某些实现不使用平台通道,你的测试在某些平台上运行时将意外地使用真实的实现。
  • 平台通道通常是插件的内部实现细节。它们可能在插件的 bug 修复更新中发生重大变化,从而意外地破坏你的测试。
  • 联邦插件的每个实现中的平台通道可能不同。例如,你可能设置了模拟平台通道以使 Windows 计算机上的测试通过,然后发现它们在 macOS 或 Linux 上运行失败。
  • 平台通道不是强类型的。例如,方法通道经常使用字典,你必须阅读插件的实现才能知道键字符串和值类型是什么。

由于这些限制,TestDefaultBinaryMessenger 主要用于插件实现的内部测试,而不是使用插件的代码的测试。

你可能还想查看 测试插件