【问题标题】:How do I access Firebase Firestore from Dart VM / Dart integration tests?如何从 Dart VM / Dart 集成测试访问 Firebase Firestore?
【发布时间】:2020-09-02 05:03:45
【问题描述】:

我正在编写一个 Flutter 应用程序,它在 Firebase Firestore 文档上具有相当复杂的逻辑。 我正在尝试使用flutter_test 编写单元测试,它实际上对数据库执行此逻辑(我知道这在技术上是一个集成测试)。这是因为这个逻辑有很多边缘情况,只有在对真实数据库进行测试时,我才能确定它们是有效的。

这似乎是一项不可能完成的任务。

  1. 由于身份验证的实现方式,cloud_firestore 包只能在手机内部运行。
  2. firebase 包有 2 个“实现”。一种只能在浏览器上运行,另一种是 Dart VM,它是 REST API 的低级包装器,几乎完全没有文档记录。

Dart VM 的 2.firebase 包有这个例子:

import 'package:firebase/firebase_io.dart';

void main() {
  var credential = ... // Retrieve auth credential
  var fbClient = new FirebaseClient(credential); // FirebaseClient.anonymous() is also available

  var path = ... // Full path to your database location with .json appended

  // GET
  var response = await fbClient.get(path);

  // DELETE
  await fbClient.delete(path);

  ...
}

...但是它没有显示如何获取credentialgoogleapis 包展示了如何获取credentials

final _credentials = new ServiceAccountCredentials.fromJson(r'''
{
  "private_key_id": ...,
  "private_key": ...,
  "client_email": ...,
  "client_id": ...,
  "type": "service_account"
}
''');

...然而这个对象不是一个字符串,它没有写在任何地方如何将它转换成FirebaseClient 类所期望的(toString() 不起作用)。 firebase 软件包上有一个Github issue 说明如何获取此凭据,但仍未得到答复。

我很难相信网上没有关于如何为 Firebase Firestore 编写适当集成测试的信息。

注意事项:

  • 我没有兴趣模拟 Firestore,因为我的逻辑很复杂,我想针对真实数据库测试每个边缘情况。
  • 我对使用Flutter Driver 没有兴趣,因为这些测试就像手机中的普通应用程序一样安装,并且在开发过程中需要时间,而且它不像常规单元测试那样直接调试。 Android Studio 有非常好的测试调试工具。

我应该如何编写访问 Firebase Firestore 的集成测试?

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    对于其他被带到这里的人,就像我几个小时前一样,通过搜索在将 dart VM 与 Firebase 一起使用时创建那个神秘的 credential 对象的方法,以下是我用于访问 Firestore 的解决方案,至少。

    工作由 Credentials 类完成:(在下面实现)

    import 'package:firebase/firebase_io.dart';
    
    String credential = await Credentials.fetch();
    FirebaseClient fbClient = new FirebaseClient(credential);
    

    Credentials 类使用 Firebase 服务帐户私钥中的数据创建凭据(Firebase 控制台 > [项目] > 设置 > 项目设置 > 服务帐户,然后下载私钥)。

    import 'dart:io';
    import 'dart:convert';
    import "package:googleapis_auth/auth_io.dart";
    import 'package:http/http.dart' as http;
    
    class Credentials {
    
      /// Returns a credential string to be used in the constructor
      /// of [FirebaseClient].
      static Future<String> fetch() async {
        Map<String, dynamic> pk = await getPrivateKey();
        // Fields from Firebase private key
        var accountCredentials = ServiceAccountCredentials.fromJson({
          "private_key_id": pk['private_key_id'],
          "private_key": pk['private_key'],
          "client_email": pk['client_email'],
          "client_id": pk['client_id'],
          "type": "service_account",
        });
    
        // Define the required scopes.
        // see https://firebase.google.com/docs/firestore/use-rest-api#working_with_google_identity_oauth_20_tokens
        var scopes = [
          "https://www.googleapis.com/auth/datastore",
        ];
    
        var client = new http.Client();
        AccessCredentials credentials =
            await obtainAccessCredentialsViaServiceAccount(
                accountCredentials, scopes, client);
        client.close();
        return credentials.accessToken.data;
      }
    
      static Future<Map<String, dynamic>> getPrivateKey() async {
        String jsonString =
            await File('/Path/to/firebase_private_key/keyfile.json')
                .readAsString();
        return json.decode(jsonString);
      }
    }
    

    【讨论】:

    • 非常感谢。有用。我编辑了您的答案以添加一些缺少的导入
    • 您好,您知道如何继续从创建侦听器到集合更改吗?
    猜你喜欢
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 2020-05-10
    • 2020-10-16
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多