将您的应用连接到 Cloud Firestore 模拟器

在将您的应用连接到 Cloud Firestore 模拟器之前,请确保您了解 Firebase Local Emulator Suite 的整体工作流,而且已安装和配置 Local Emulator Suite 并已查看其 CLI 命令

选择一个 Firebase 项目

Firebase Local Emulator Suite 模拟的是单个 Firebase 项目的产品。

如需选择要使用的项目,请在启动模拟器之前,使用 CLI 在工作目录下运行 firebase use。或者,您也可以向每个模拟器命令传递 --project 标志。

Local Emulator Suite 支持模拟实际 Firebase 项目和演示项目。

项目类型 功能 与模拟器结合使用
实际

实际 Firebase 项目就是您创建和配置的项目(很可能是通过 Firebase 控制台创建和配置)。

实际项目具有实时资源,例如数据库实例、存储桶、函数或您为该 Firebase 项目设置的任何其他资源。

使用实际的 Firebase 项目时,您可以为任何或所有受支持的产品运行模拟器。

对于您未模拟的任何产品,您的应用和代码都将与实时资源(数据库实例、存储桶、函数等)交互。

演示

演示 Firebase 项目没有实际 Firebase 配置,也没有实时资源。通常可通过 Codelab 或其他教程来访问这些项目。

演示项目的 ID 带有 demo- 前缀。

使用演示 Firebase 项目时,您的应用和代码仅与模拟器交互。如果您的应用尝试与您没有为其运行模拟器的资源进行交互,该代码将失败。

我们建议您尽可能使用演示项目。优点包括:

  • 设置更简单,您无需创建 Firebase 项目也可运行模拟器
  • 安全性更强,就算您的代码意外调用了非模拟(生产环境)资源,也不可能发生数据更改、使用资源或产生费用
  • 提供更好的离线支持,无需访问互联网即可下载您的 SDK 配置。

对应用进行插桩 (instrument) 处理以便与模拟器通信

启动时,Cloud Firestore 模拟器会为 firebase.json 文件中的每个 firestore 配置创建一个默认数据库和一个已命名的数据库。

系统还会隐式创建已命名的数据库,以响应对引用特定数据库的模拟器的任何 SDK 或 REST API 调用。这种隐式创建的数据库以开放规则运行。

如需在 Emulator Suite UI 中以交互方式使用默认数据库和已命名的数据库,请在浏览器的地址栏中更新网址,以选择默认数据库或已命名的数据库。

  • 例如,要浏览默认数据库实例中的数据,请将网址更新为 localhost:4000/firestore/default/data
  • 要浏览名为 ecommerce 的数据库实例中的数据,请将网址更新为 localhost:4000/firestore/ecommerce/data

Android、Apple 平台和 Web SDK

按如下方式设置您的应用内配置或测试类,以便与 Cloud Firestore 进行交互。请注意,在下例中,应用代码会连接到默认项目数据库。如需查看涉及默认数据库之外的其他 Cloud Firestore 数据库的示例,请参阅多个数据库的指南

Kotlin+KTX
// 10.0.2.2 is the special IP address to connect to the 'localhost' of
// the host computer from an Android emulator.
val firestore = Firebase.firestore
firestore.useEmulator("10.0.2.2", 8080)

firestore.firestoreSettings = firestoreSettings {
    isPersistenceEnabled = false
}
Java
// 10.0.2.2 is the special IP address to connect to the 'localhost' of
// the host computer from an Android emulator.
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
firestore.useEmulator("10.0.2.2", 8080);

FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
        .setPersistenceEnabled(false)
        .build();
firestore.setFirestoreSettings(settings);
Swift
let settings = Firestore.firestore().settings
settings.host = "127.0.0.1:8080"
settings.cacheSettings = MemoryCacheSettings()
settings.isSSLEnabled = false
Firestore.firestore().settings = settings

Web

import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";

// firebaseApps previously initialized using initializeApp()
const db = getFirestore();
connectFirestoreEmulator(db, '127.0.0.1', 8080);

Web

// Firebase previously initialized using firebase.initializeApp().
var db = firebase.firestore();
if (location.hostname === "localhost") {
  db.useEmulator("127.0.0.1", 8080);
}

使用模拟器测试由 Firestore 事件触发的 Cloud Functions 函数时无需进行额外设置。当 Firestore 和 Cloud Functions 模拟器都在运行时,它们会自动协同工作。

Admin SDK

设置 FIRESTORE_EMULATOR_HOST 环境变量后,Firebase Admin SDK 会自动连接到 Cloud Firestore 模拟器:

export FIRESTORE_EMULATOR_HOST="127.0.0.1:8080"

如果您的代码在 Cloud Functions 模拟器中运行,系统会在调用 initializeApp 时自动设置您的项目 ID 和其他配置。

如果您希望 Admin SDK 代码连接到在其他环境中运行的共享模拟器,则需要指定您使用 Firebase CLI 设置的同一项目 ID。您可以直接将项目 ID 传递给 initializeApp 或设置 GCLOUD_PROJECT 环境变量。

Node.js Admin SDK
admin.initializeApp({ projectId: "your-project-id" });
环境变量
export GCLOUD_PROJECT="your-project-id"

在两轮测试的间隙清空数据库

Firestore 生产实例不提供用于刷新 (flush) 数据库的平台 SDK 方法,但 Firestore 模拟器提供一个专用于此用途的 REST 端点,您可通过测试框架的“setup/tearDown”步骤、测试类或 shell(例如使用 curl)调用此端点,然后再开始测试。此方法可用作停止模拟器进程的替代方法。

在相应的方法中,执行 HTTP DELETE 操作,将您的 Firebase projectID(例如 firestore-emulator-example)提供给以下端点:

"http://localhost:8080/emulator/v1/projects/firestore-emulator-example/databases/(default)/documents"

当然,您的代码应等待关于刷新完成或失败的 REST 确认信息。

您可以通过 shell 执行此操作:

// Shell alternative…
$ curl -v -X DELETE "http://localhost:8080/emulator/v1/projects/firestore-emulator-example/databases/(default)/documents"

完成这样的步骤后,您可以对测试进行排序并触发函数,确保在两轮运行的间隙清除旧数据,从而使用全新的基准测试配置。

导入和导出数据

通过数据库模拟器和 Cloud Storage for Firebase 模拟器,您可以从正在运行的模拟器实例中导出数据。定义要在单元测试或持续集成工作流中使用的基准数据集,然后将其导出以供团队共享。

firebase emulators:export ./dir

在测试中,当模拟器启动时,导入基准数据。

firebase emulators:start --import=./dir

您可以指示模拟器在关停时导出数据,方法是指定导出路径,或是直接使用传递给 --import 标志的路径。

firebase emulators:start --import=./dir --export-on-exit

这些数据导入和导出选项也适用于 firebase emulators:exec 命令。如需了解详情,请参阅模拟器命令参考文档

直观呈现安全规则活动

在逐步完成原型设计和测试循环时,您可以使用 Local Emulator Suite 提供的可视化工具和报告。

使用请求监控器

借助 Cloud Firestore 模拟器,您可以在 Emulator Suite UI 中直观呈现客户端请求,包括对 Firebase Security Rules 的评估跟踪。

打开“Firestore”>“请求”标签页,以查看每个请求的详细评估序列。

显示安全规则评估的 Firestore 模拟器请求监控器

直观呈现规则评估报告

在向原型设计添加安全规则时,您可以使用 Local Emulator Suite 调试工具调试这些规则。

运行一系列测试后,您可以访问测试范围报告,其中显示了每条安全规则的评估结果。

如需获取该报告,请在模拟器运行时查询其上的公开端点。如需适用于浏览器的版本,请使用以下网址:

http://localhost:8080/emulator/v1/projects/<database_name>:ruleCoverage.html

这会将您的规则分解为表达式和子表达式,您可以将鼠标悬停在相应表达式上以了解更多信息(包括评估次数和返回的值)。如需这些数据的原始 JSON 版本,请在查询中包含以下网址:

http://localhost:8080/emulator/v1/projects/<database_name>:ruleCoverage

此处的 HTML 版本报告突出显示了抛出未定义和空值错误的评估:

Cloud Firestore 模拟器与生产环境的区别

Cloud Firestore 模拟器会尝试真实地重现生产服务的行为,但存在一些值得注意的限制。

Cloud Firestore 的多数据库支持

目前,Emulator Suite UI 支持对默认数据库进行交互式创建、修改、删除、请求监控和安全可视化操作,但不支持其他已命名的数据库。

不过,模拟器本身会根据 firebase.json 文件中的配置隐式创建已命名的数据库,以响应 SDK 或 REST API 调用。

交易

模拟器目前并不能实现生产环境中发生的所有事务行为。当您要测试涉及对一个文档执行多次并发写入的功能时,模拟器完成写入请求的速度可能会很慢。在某些情况下,对数据的锁定可能需要长达 30 秒才会解除。如有需要,请考虑相应地调整测试超时时长。

索引

模拟器不会跟踪复合索引,而是执行任何有效查询。请务必对真实的 Cloud Firestore 实例测试您的应用,以确定您需要哪些索引。

限制

模拟器不会强制执行生产环境中强制执行的所有限制。例如,模拟器可能会允许因为过大而会被生产服务拒绝的事务。请确保您熟悉文档中说明的限制,并且将您的应用设计为主动避免超出这些限制。

后续步骤