如何从客户端使用Firestore模拟器

时间:2019-08-17 14:05:49

标签: javascript firebase google-cloud-firestore google-cloud-functions firebase-tools

我想在本地测试我的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中设置模拟器网址

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

firebase.initializeApp(firebaseConfig)

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

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

1)在函数仿真器中使用远程Firestore

OR

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

任何人都已经做到了吗?

5 个答案:

答案 0 :(得分:2)

安装测试库

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

来自“ Test your Cloud Firestore Security Rules”的注释

  

写入Cloud Firestore模拟器的数据将保留在内存中,直到   仿真器已停止。如果仿真器连续运行,则可能   对测试隔离有影响。确保将数据写入一个   测试不在另一个中读取,或者使用   clearFirestoreData,或为每个项目分配不同的项目ID   独立测试:调用firebase.initializeAdminApp或   firebase.initializeTestApp,附加用户ID,时间戳或随机   projectID的整数。

答案 1 :(得分:1)

我也有同样的问题。我找到了以下示例,看起来它仍在进行中:

https://github.com/firebase/quickstart-nodejs/tree/master/firestore-emulator/browser-quickstart

在示例中,他们没有直接使用@firebase/testing。当我确实尝试将@firebase/testing嵌入到我的Webpack代码中时,它尝试通过grpc进行连接,而尝试进行fs.existsSync的连接,这在webpack浏览器上下文中不存在。他们宁愿通过WebChannel启用该功能。

截至2019年11月的一些警告:

  • 您可能会在使用X-Goog-API连接到localhost:8080的控制台中看到错误。我不确定这是干什么的。
  • 您可能会收到以下错误:@firebase/firestore: Firestore (6.3.5): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds.

尽管存在这些错误,我的函数仍然能够连接到本地Firestore。

我测试时使用的版本:

  • firebase-js-sdk 6.3.1
  • firebase-tools 7.3.1

更新11/18:

  • 我在quickstart-nodejs github中提出了一个问题,看来我只需要使用所有内容的最新版本。

版本:

  • firebase-js-sdk v7.4.0
  • firebase-tools v7.8.0

答案 2 :(得分:1)

好吧,这很简单...在Firestore的科学配置中,您应该提供主机,而不是Firestore的来源(使用ssl参数设置协议):

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

当我遇到完全相同的错误时,至少这为我解决了这个问题。

仅供参考,对于正在阅读此书的任何人-如果您在Firestore客户端中遇到问题,都可以使用debug级日志记录,只需设置firebase.firestore.setLogLevel('debug')。如果OP做到了这一点,他可能已经注意到firebase正在访问http://http://localhost:8080/ ...上的firestore ...

答案 3 :(得分:0)

好吧,我找到了怎么做:

1)在本地启动功能仿真器:

set GOOGLE_APPLICATION_CREDENTIALS=./privatekey.json && firebase serve --only functions

2)然后是客户端:

if (process.env.NODE_ENV === 'development') {
    firebase.functions().useFunctionsEmulator('http://localhost:5001')
}

答案 4 :(得分:0)

定义FIRESTORE_EMULATOR_HOST环境变量

如果使用的库支持FIRESTORE_EMULATOR_HOST环境变量,请运行:

导出FIRESTORE_EMULATOR_HOST = localhost:8080

或只需将 FIRESTORE_EMULATOR_HOST = localhost:8080 添加到您的.env文件中