Flutter 测试中的插件
将插件作为 Flutter 测试的一部分。
几乎所有 Flutter 插件 都包含两部分:
Dart code, which provides the API your code calls.
-
Code written in a platform-specific (or "host") language, such as Kotlin or Swift, which implements those APIs.
Dart 代码,提供你的代码所调用的 API。
-
用平台特定(或「宿主」)语言编写的代码,例如 Kotlin 或 Swift,用于实现这些 API。
事实上,原生(或宿主)语言代码是插件包与标准包的区别所在。
构建并注册插件的宿主部分是
Flutter 应用构建流程的一部分,因此插件仅在你的代码运行于应用中时有效,例如通过 flutter run
或运行集成测试时。运行 Dart 单元测试 或
widget 测试
时,宿主代码不可用。如果你测试的代码调用了任何插件,通常会出现如下错误:
MissingPluginException(No implementation found for method someMethodName on channel some_channel_name)
在单元测试使用插件的代码时,有几种方式可避免此异常。以下解决方案按推荐顺序列出。
封装插件
#在大多数情况下,最佳做法是将插件调用封装在你自己的 API 中,并在测试中提供 mock 你自己 API 的方式。
这有几个优点:
-
If the plugin API changes, you won't need to update your tests.
-
You are only testing your own code, so your tests can't fail due to behavior of a plugin you're using.
-
You can use the same approach regardless of how the plugin is implemented, or even for non-plugin package dependencies.
-
如果插件 API 变更,你无需更新测试。
-
你只测试自己的代码,因此测试不会因你使用的插件行为而失败。
-
无论插件如何实现,甚至对于非插件包依赖,你都可以使用相同方法。
Mock 插件的公共 API
#如果插件 API 已基于类实例,你可以直接 mock,但需注意以下限制:
-
This won't work if the plugin uses non-class functions or static methods.
-
Tests will need to be updated when the plugin API changes.
-
如果插件使用非类函数或静态方法,此方法无效。
-
插件 API 变更时需要更新测试。
Mock 插件的平台接口
#如果插件是联合插件,它会包含一个平台接口,允许注册其内部逻辑的实现。你可以注册该平台接口实现的 mock,而不是公共 API,但需注意以下限制:
This won't work if the plugin isn't federated.
-
Your tests will include part of the plugin's code, so plugin behavior could cause problems for your tests. For instance, if a plugin writes files as part of an internal cache, your test behavior might change based on whether you had run the test previously.
Tests might need to be updated when the platform interface changes.
如果插件不是联合插件,此方法无效。
-
你的测试将包含插件的部分代码,因此插件行为可能给你的测试带来问题。例如,如果插件将文件写入内部缓存,测试行为可能取决于你是否曾运行过该测试。
平台接口变更时可能需要更新测试。
可能需要这样做的一个例子是 mock 你所依赖的包使用的插件实现,而不是你自己的代码,因此你无法更改其调用方式。不过,如果可能,你应改为 mock 使用该插件的依赖。
Mock 平台通道
#
如果插件使用平台通道,你可以使用
TestDefaultBinaryMessenger
mock 平台通道。仅当出于某种原因上述方法都不可用时才应使用,因为它有几个缺点:
-
Only implementations that use platform channels can be mocked. This means that if some implementations don't use platform channels, your tests will unexpectedly use real implementations when run on some platforms.
-
Platform channels are usually internal implementation details of plugins. They might change substantially even in a bugfix update to a plugin, breaking your tests unexpectedly.
-
Platform channels might differ in each implementation of a federated plugin. For instance, you might set up mock platform channels to make tests pass on a Windows machine, then find that they fail if run on macOS or Linux.
-
Platform channels aren't strongly typed. For example, method channels often use dictionaries and you have to read the plugin's implementation to know what the key strings and value types are.
-
只有使用平台通道的实现才能被 mock。这意味着如果某些实现不使用平台通道,在某些平台上运行时测试会意外使用真实实现。
-
平台通道通常是插件的内部实现细节。即使在插件的 bug 修复更新中也可能大幅变更,导致测试意外失败。
-
联合插件的每种实现中平台通道可能不同。例如,你可能设置 mock 平台通道使测试在 Windows 机器上通过,却发现若在 macOS 或 Linux 上运行会失败。
-
平台通道不是强类型的。例如,method channel 常使用字典,你必须阅读插件实现才能知道键字符串和值类型。
由于这些限制,TestDefaultBinaryMessenger
主要用于插件实现的内部测试,而不是使用插件的代码的测试。
你也可以参阅 测试插件。
除非另有说明,本文档之所提及适用于 Flutter 3.44.0 版本。本页面最后更新时间:2026-06-04。查看文档源码 或者 为本页面内容提出建议。