首页 > 解决方案 > 如何从客户端使用 Firestore 模拟器

问题描述

我想在本地测试我的 firebase 功能。这些函数进行 firestore 查询。

所以我启动模拟器firebase emulators:start并在我的客户端中使用firebase.functions().useFunctionsEmulator('http://localhost:5001').

当我在客户端调用它们时,我的函数运行良好。我可以在 Firestore 模拟器中读/写数据。

问题 :

我想直接在我的客户端内读取 firestore 模拟器数据,例如:

firebase.firestore().collection('tests').get().then(tests => {
    console.log( tests.docs.map(test=>test.map) )
})

但我找不到如何在我的客户端中设置 firestore 模拟器。

我在这里尝试过:

1) Firestore 设置

firebase.firestore().settings({
    host:'http://localhost:8080',
    ssl:false
})

结果 :

@firebase/firestore: Firestore (6.3.5): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds.进入我的客户端控制台。

http 请求返回“未找到”

2)在我的firebaseConfig中设置模拟器url

var firebaseConfig = {
    // ...
    databaseURL: "http://localhost:8080",
    // ...
}

firebase.initializeApp(firebaseConfig)

在这种情况下,请求远程服务器 ( https://firestore.googleapis.com. .)。

所以我想设置这两种情况之一:

1)在我的功能模拟器中使用远程火库

或者

2)在我的客户端代码中使用本地 Firestore 模拟器。

有人已经这样做了吗?

标签: javascriptfirebasegoogle-cloud-firestoregoogle-cloud-functionsfirebase-tools

解决方案


安装测试库

npm i -D @firebase/testing

在另一个终端中设置并启动模拟器:

firebase setup:emulators:firestore

firebase serve --only firestore

设置测试

const firebase = require("@firebase/testing");

// Helper function to setup test db
function authedApp(auth) {
  return firebase
    .initializeTestApp({ projectId: FIRESTORE_PROJECT_ID, auth })
    .firestore();
}

// Setup methods
beforeEach(async () => {
  // Clear the database between tests
  await firebase.clearFirestoreData({ projectId: FIRESTORE_PROJECT_ID });
});

// Clean up apps between tests.
afterEach(async () => {
  await Promise.all(firebase.apps().map(app => app.delete()));
});

运行测试

it("should retrieve correct item", async () => {
  // Init test db
  const db = authedApp(null);

  // Manually add item to collection
  const ref = await db.collection(COLLECTION_NAME).add({name: 'test item'});

  // Fetch item by id 
  const resp = await db.collection(COLLECTION_NAME).doc(ref.id).get();

  // test the output
  expect(resp).toBeDefined();
  expect(resp).toEqual(expect.objectContaining({name: 'test item'}));
});

当然,您的特定设置和情况会有所不同,但这至少应该给您一个大致的概念。更多信息:https ://firebase.google.com/docs/rules/unit-tests

“测试您的 Cloud Firestore 安全规则”中的注释

写入 Cloud Firestore 模拟器的数据会保存在内存中,直到模拟器停止。如果模拟器连续运行,这可能会对测试隔离产生影响。要确保在一个测试中写入的数据不会在另一个测试中读取,请使用 明确清除您的数据 clearFirestoreData,或者为每个独立测试分配不同的项目 ID:当您调用 firebase.initializeAdminApp 或 firebase.initializeTestApp 时,附加用户 ID、时间戳、或 projectID 的随机整数。

编辑:我不久前写了一篇博客文章,其中详细介绍了该主题。


推荐阅读