跳转至正文

Flutter 测试中的插件

将插件作为 Flutter 测试的一部分。

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

  • Dart 代码,提供你的代码所调用的 API。

  • 用平台特定(或「宿主」)语言编写的代码,例如 Kotlin 或 Swift,用于实现这些 API。

事实上,原生(或宿主)语言代码是插件 package 与标准 package 的区别所在。

构建并注册插件的宿主部分是 Flutter 应用构建流程的一部分,因此插件仅在你的代码运行于应用中时有效,例如通过 flutter run 或运行 集成测试 时。运行 Dart 单元测试widget 测试 时,宿主代码不可用。如果你测试的代码调用了任何插件,通常会出现如下错误:

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

在单元测试使用插件的代码时,有几种方式可避免此异常。以下解决方案按推荐顺序列出。

封装插件

#

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

这有几个优点:

  • 如果插件 API 变更,你无需更新测试。

  • 你只测试自己的代码,因此测试不会因你使用的插件行为而失败。

  • 无论插件如何实现,甚至对于非插件 package 依赖,你都可以使用相同方法。

Mock 插件的公共 API

#

如果插件 API 已基于类实例,你可以直接 mock,但需注意以下限制:

  • 如果插件使用非类函数或静态方法,此方法无效。

  • 插件 API 变更时需要更新测试。

Mock 插件的平台接口

#

如果插件是 联合插件,它会包含一个平台接口,允许注册其内部逻辑的实现。你可以注册该平台接口实现的 mock,而不是公共 API,但需注意以下限制:

  • 如果插件不是联合插件,此方法无效。

  • 你的测试将包含插件的部分代码,因此插件行为可能给你的测试带来问题。例如,如果插件将文件写入内部缓存,测试行为可能取决于你是否曾运行过该测试。

  • 平台接口变更时可能需要更新测试。

可能需要这样做的一个例子是 mock 你所依赖的 package 使用的插件实现,而不是你自己的代码,因此你无法更改其调用方式。不过,如果可能,你应改为 mock 使用该插件的依赖。

Mock 平台通道

#

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

  • 只有使用平台通道的实现才能被 mock。这意味着如果某些实现不使用平台通道,在某些平台上运行时测试会意外使用真实实现。

  • 平台通道通常是插件的内部实现细节。即使在插件的 bug 修复更新中也可能大幅变更,导致测试意外失败。

  • 联合插件的每种实现中平台通道可能不同。例如,你可能设置 mock 平台通道使测试在 Windows 机器上通过,却发现若在 macOS 或 Linux 上运行会失败。

  • 平台通道不是强类型的。例如,method channel 常使用字典,你必须阅读插件实现才能知道键字符串和值类型。

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

你也可以参阅 测试插件