11

美好的一天,我正在尝试对以下在 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;
  };

测试.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(No implementation found for method Firestore#runTransaction on channel plugins.flutter.io/cloud_firestore)

但我不明白为什么因为我拥有所有依赖项,如果我在另一个类中调用该函数,则会创建文档。但是在这个测试中调用会出现上述错误。我想我没有以正确的方式做这件事。

我可以查看的任何贡献或任何参考资料都可以帮助测试此类功能吗?

4

2 回答 2

0

TLDR:mazei513 的评论是正确的。由于 Flutter Firestore 是一个插件而不是一个包,它需要一个平台来运行。例如,该平台可以是 iOS 手机或 Android 虚拟设备。因此,您不能编写单元测试来测试 Firestore 命令。您必须使用integration_test包来执行这种测试。

了解插件与包之间的区别

文档所述,一个插件

是一种特殊的包,它使应用程序可以使用平台功能。可以为 Android(使用 Kotlin 或 Java)、iOS(使用 Swift 或 Objective-C)、web、macOS、Windows、Linux 或其任何组合编写插件包。

如果您查看 中的 Firestore 插件/usr/local/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.7.0,您会看到:

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 虚拟设备。例如,你这个用于 Github 操作。然后您可以从命令行启动模拟器。
  • 使用Firebase 测试实验室。我没有使用它,但它应该可以工作。

使用 integration_test

按照此文档integration_test为您的项目进行配置。不要忘记使用testWidgets而不是test这样可以在设备模拟器中而不是在 Dart 简单环境中启动测试。

完成后,所有集成/端到端测试都可以使用flutter test integration_test.

不要弄乱你的生产数据库

如果您按原样启动该命令flutter test integration_test,则测试中存在的文档很有可能{'name':'Dev','title':'Dev'}会出现在您的生产数据库中。

为了解决这个问题,您主要有两种选择:

  1. 设置一个用于测试的真实 Firebase 项目
  2. 使用Firebase 本地模拟器套件

对于我的项目,我选择了第二个选项。使用单个命令,您可以启动 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 env var 启动集成测试

关于模拟/伪造 Firestore

我不建议您模拟或伪造 Firestore,因为这对您而言毫无意义。如果您要测试的是您实际上可以在 Firestore 中正确编写,那么在 Firestore 中使用双精度是没有意义的。

但是,在某些情况下,它可能很有用。例如,对在某些时候写入或查询 Firestore 的业务行为进行单元测试。

同样,您有几种解决方案:

  • 你可以自己模拟 Firestore,就像在这里完成的一样。但是做IMO是相当复杂和痛苦的。
  • 您可以使用包fake_cloud_firestore。顾名思义,这是一个完整的 Cloud Firestore 假货。到目前为止,一切都很好,它对我来说非常有效。
于 2021-12-24T14:04:26.460 回答
0

自从这个问题提交以来已经有一段时间了,但只是为了不让它没有回复。

当我偶然发现同样的错误时,我发现了这个有用的问题:https ://github.com/flutter/flutter/issues/13971

基本上重新安装所有软件包:

flutter clean
flutter packages get

希望能帮助到你。

于 2019-09-03T14:22:31.610 回答