Flutter Firebase 函数的单元测试
Posted
技术标签:
【中文标题】Flutter Firebase 函数的单元测试【英文标题】:Unit Testing On Flutter Firebase functions 【发布时间】:2019-04-13 00:40:54 【问题描述】:美好的一天,我正在尝试对以下在 Cloud Firestore 中创建文档的函数执行一些单元测试。我在我的应用程序中使用了一个函数,它创建了一个文档,但我想编写一个 test.dart 文件,该文件对以下函数执行单元测试,甚至在控制台上打印一些输出以进行验证。
我认为我没有以正确的方式编写我的 Test.dart。我收到一个错误。
createdatabase.dart 文件中的函数
Future<dynamic> createDoc(dataMap,collection) async
final TransactionHandler createTransaction = (Transaction tx) async
final DocumentSnapshot ds = await tx.get(db.collection(collection).document());
final Map<String, dynamic> result = ;
result.addAll(dataMap);
result['id'] = ds.documentID;
await tx.set(ds.reference, result);
return result;
;
Test.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:test/test.dart';
import '../lib/service/createfirebase.dart';
void main()
CreateFirebase cf = new CreateFirebase();
//test
test('Creating doc on firestore ', () async
Object dataObj ='name':'Dev','title':'Dev';
var create = await cf.createDoc(dataObj, 'crude');
expect(true,create);
print('The doc details are');
print(dataObj);
);
运行此测试后的错误是 MissingPluginException(在通道 plugins.flutter.io/cloud_firestore 上找不到方法 Firestore#runTransaction 的实现)
但我不明白为什么,因为我拥有所有依赖项,并且如果我在另一个类中调用该函数,则会创建文档。但是在这个测试中调用会出现上述错误。我想我的做法不对。
我可以查看任何有助于测试此类功能的贡献或任何参考资料?
【问题讨论】:
据我了解,插件使用平台特定代码运行,这意味着如果它在 android 上运行,它将运行 Java/Kotlin 代码。在内部测试中,它不会有任何平台代码可以运行。这使您可以选择在 Firestore 中使用 driver test 或 mock。 【参考方案1】:TLDR:mazei513 的评论是正确的。由于 Flutter Firestore 是一个插件而不是一个包,它需要一个平台来运行。例如,该平台可以是 ios 手机或 Android 虚拟设备。因此,您不能编写 unit 测试来测试 Firestore 命令。您必须使用integration_test 包来执行此类测试。
了解插件与包之间的区别
正如doc 所说,一个插件
是一种特殊的包,它使平台功能 可用于应用程序。可以为 Android 编写插件包 (使用 Kotlin 或 Java)、iOS(使用 Swift 或 Objective-C)、web、macOS、 Windows、Linux 或其任意组合。
如果您查看 /usr/local/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.7.0
中的 Firestore 插件,您会看到:
jjanvier:nouba$ ls -l /usr/local/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.7.0
total 48
drwxr-xr-x 4 jjanvier jjanvier 4096 Oct 6 17:20 android
drwxr-xr-x 3 jjanvier jjanvier 4096 Oct 6 17:20 ios
drwxr-xr-x 3 jjanvier jjanvier 4096 Oct 6 17:20 lib
drwxr-xr-x 3 jjanvier jjanvier 4096 Oct 6 17:20 macos
-rw-r--r-- 1 jjanvier jjanvier 912 Oct 6 17:20 pubspec.yaml
由于 Firebase 插件实际上根据平台(Android、iOS、MacOS...)运行本机代码,因此它们需要在“真实”设备上运行。因此,它不适用于flutter test
,它只是一个简单的 Dart 执行器。
测试 Firestore 存储库(或命令或查询)
关于设备模拟器
要获得一个可以运行测试的平台,您有多种选择。例如:
从您的 IDE 启动 Android 虚拟设备。这就是我在本地工作时所做的。 在您的持续集成管道上设置 Android 虚拟设备。例如,您 this one 用于 Github 操作。然后你可以在命令行中start the emulator。 使用Firebase Test Lab。我没有使用它,但它应该可以工作。使用 integration_test
关注this documentation为您的项目配置integration_test
。不要忘记使用testWidgets
而不是test
,因为这样可以在设备模拟器而不是在 Dart 简单环境中启动测试。
完成后,所有集成/端到端测试都可以使用flutter test integration_test
启动。
不要弄乱你的生产数据库
如果您按原样启动命令flutter test integration_test
,则测试中存在的文档'name':'Dev','title':'Dev'
很有可能会出现在您的生产数据库中。
为了解决这个问题,您主要有两种选择:
-
设置一个用于测试的真实 Firebase 项目
使用Firebase local emulator suite
对于我的项目,我选择了第二个选项。只需一条命令,您就可以启动 Firebase 模拟器、加载设备并运行测试:
firebase --config="firebase.test.json" emulators:exec --import fixtures/ "flutter test integration_test/ --dart-define=FOO=bar"
让我们详细说明一下命令:
--config="firebase.test.json"
使用这个配置文件启动 firebase。这允许我在启动测试时保持本地模拟器套件运行
--import fixtures/
:将文件夹“fixtures”加载为数据集
emulators:exec "flutter test integration_test/ --dart-define=FOO=bar"
:使用 FOO 环境变量启动集成测试
关于模拟/伪造 Firestore
我不建议您模拟或伪造 Firestore,因为这对您而言毫无意义。如果您想测试的是您实际上可以在 Firestore 中正确写入,那么在 Firestore 中使用双精度是没有意义的。
但是,在某些情况下它可能很有用。例如,对在某些时候写入或查询 Firestore 的业务行为进行单元测试。
同样,您有几种解决方案:
您可以自己模拟 Firestore,like it's done here。但是做 IMO 是相当复杂和痛苦的。 您可以使用包fake_cloud_firestore。顾名思义,这是一个完整的 Cloud Firestore 假货。到目前为止,一切都很好,非常适合我。【讨论】:
【参考方案2】:自从这个问题提交以来已经有一段时间了,但只是为了不让它没有回复。
当我偶然发现同样的错误时,我发现了这个有用的问题:https://github.com/flutter/flutter/issues/13971
基本上重新安装所有软件包:
flutter clean
flutter packages get
希望对你有帮助。
【讨论】:
以上是关于Flutter Firebase 函数的单元测试的主要内容,如果未能解决你的问题,请参考以下文章
如何从 firebase_auth 测试“signInWithEmailAndPassword”
如何使用 Firebase Cloud Firestore 对方法进行单元测试?
Flutter Firebase Functions:调用函数时出错
从 Flutter 应用通过本地网络连接到 Firebase 函数模拟器