我想在本地测试我的火力基础函数。 这些函数进行火烧存储查询。
所以我firebase emulators:start
启动模拟器,在我的客户端中使用firebase.functions().useFunctionsEmulator('http://localhost:5001')
.
当我在客户端中调用它们的函数时,它们的函数运行良好。我可以在火堆模拟器中读取/写入数据。
问题 :
我想直接在客户端中读取 firestore 模拟器数据,例如:
firebase.firestore().collection('tests').get().then(tests => {
console.log( tests.docs.map(test=>test.map) )
})
但是我找不到如何在客户端中设置Firestore模拟器。
这是我尝试过的:
1( 恢复设置
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( 在我的函数模拟器中使用远程火库
或
2( 在我的客户端代码中使用本地 firestore 模拟器。
有人已经这样做了吗?
安装测试库
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
"测试云 Firestore 安全规则"中的说明
写入云 Firestore 模拟器的数据将保留在内存中,直到 模拟器已停止。如果模拟器连续运行,这可能会 对测试隔离有影响。确保数据写入一体 测试未在另一个中读取,要么显式清除您的数据
clearFirestoreData
,或为每个项目分配不同的项目 ID 独立测试:当您致电 firebase.initializeAdminApp 或 firebase.initializeTestApp,附加用户 ID、时间戳或随机 整数到项目 ID。
编辑:不久前我写了一篇博客文章,其中详细介绍了该主题。
我也有同样的问题。我找到了以下示例,看起来它仍在进行中:
https://github.com/firebase/quickstart-nodejs/tree/master/firestore-emulator/browser-quickstart
他们没有在他们的示例中直接使用@firebase/testing
。当我尝试在我的 webpack 代码中嵌入@firebase/testing
时,它会尝试通过grpc
进行连接,这试图执行fs.existsSync
,这webpack
浏览器上下文中不存在。他们更喜欢通过网络渠道启用该功能。
截至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.
尽管有这些错误,但我的函数仍然能够连接到当地的消防站。
我在测试时拥有的版本:
- Firebase-JS-SDK 6.3.1
- Firebase-Tools 7.3.1
更新 11/18:
- 我在 github 中提出了一个问题
quickstart-nodejs
似乎我只需要使用所有内容的最新版本。
版本:
- Firebase-JS-SDK v7.4.0
- Firebase-Tools v7.8.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')
}
好吧,这是微不足道的...在 firestore cient 配置中,您应该提供主机,而不是 firestore 的源(协议使用ssl
参数设置(:
firebase.firestore().settings({
host: 'localhost:8080',
ssl: false
})
至少当我遇到完全相同的错误时,这为我解决了它。
仅供参考,任何正在阅读本文的人 - 如果您在使用 firestore 客户端时遇到问题,您可以使用debug
级日志记录,只需设置firebase.firestore.setLogLevel('debug')
即可。如果OP这样做了,他可能会注意到火力基地正在http://http://localhost:8080/
进入火库......
定义FIRESTORE_EMULATOR_HOST环境变量
如果您使用的是支持 FIRESTORE_EMULATOR_HOST 环境变量的库,请运行:
导出FIRESTORE_EMULATOR_HOST=本地主机:8080
或者只需将FIRESTORE_EMULATOR_HOST=localhost:8080添加到您的 .env 文件中