跳至主要内容

Flutter 测试中的插件

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

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

事实上,原生(或主机)语言代码将插件包与标准包区分开来。

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

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

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

包装插件

#

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

这有几个优点

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

模拟插件的公共 API

#

如果插件的 API 已经基于类实例,您可以直接模拟它,但有以下注意事项

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

模拟插件的平台接口

#

如果插件是 联合插件,它将包含一个平台接口,允许注册其内部逻辑的实现。您可以注册该平台接口实现的模拟,而不是使用以下注意事项的公共 API

  • 如果插件不是联合插件,则此方法无效。
  • 您的测试将包含插件代码的一部分,因此插件行为可能会导致测试出现问题。例如,如果插件在内部缓存的一部分中写入文件,则您的测试行为可能会根据您是否以前运行过测试而改变。
  • 平台接口更改时可能需要更新测试。

这可能需要的一个示例是模拟您依赖的包使用的插件的实现,而不是您自己的代码,因此您无法更改其调用方式。但是,如果可能,您应该模拟使用该插件的依赖项。

模拟平台通道

#

如果插件使用 平台通道,您可以使用 TestDefaultBinaryMessenger 模拟平台通道。仅当出于某种原因,上述方法均不可用时才应使用此方法,因为它有几个缺点

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

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

您可能还想查看 插件测试