为什么我在使用模拟器执行测试时仍然从生产中获取 firestore 数据?
why I am still getting firestore data from production when performing testing using emulator?
我正在使用
- 节点 14
- firebase 函数测试:0.2.3
- firebase-admin: 9.6.0
- firebase 函数:3.13.2
- firebase 工具:9.10.0
我正在尝试对预定的云功能执行单元测试。我的云函数是这样的
export const deleteExpiredEvents = functions
.pubsub.schedule("0 0 * * *")
.timeZone("Asia/Jakarta")
.onRun(async (context) => {
// delete expired events
});
我这样测试上面的功能
import * as admin from "firebase-admin";
import * as firebase from "firebase-functions-test";
const test = firebase({
databaseURL: "https://xxxx.firebaseio.com",
projectId: projectID,
}, "./service-account.json");
const db = admin.initializeApp().firestore();
beforeEach( async () => {
// create dummy expired event
await db.doc(`events/${event1.eventID}`).set(event1);
await db.doc(`events/${event2.eventID}`).set(event2);
await db.doc(`events/${event3.eventID}`).set(event3);
});
it("should not delete events that not expired", async () => {
const wrap = test.wrap(myFunctions.deleteExpiredEvents);
const context = {};
wrap(context); // execute function
const querySnapshot = await db.collection("events").get();
querySnapshot.docs.forEach((snapshot) => console.log(snapshot.data().eventID));
// the rest of my code test ....
});
正如您从上面的代码中看到的,在 before
块中,我尝试创建虚拟事件数据,因此我希望我的 firestore 模拟器将填充这 3 个虚拟事件数据。
然后在 it
块中,我尝试获取所有事件,然后 console.log
所有 eventID
s
我预计我将从之前在 before
块中创建的 firestore 模拟器获得 3 个事件,但我不知道为什么我获得 74 个事件(而不是仅仅 3 个),它来自 firestore生产数据,不是来自 firestore 模拟器
我相信我在执行测试时已经 运行 firebase emulators:start
、firestore、函数和 pubsub 模拟器 运行ning。
为什么我在模拟器启动后仍然从生产中获取 firestore 数据?
我尝试从这里阅读文档:https://firebase.google.com/docs/emulator-suite/connect_firestore
据说:
The Firebase Admin SDKs automatically connect to the Cloud Firestore
emulator when the FIRESTORE_EMULATOR_HOST environment variable is set:
export FIRESTORE_EMULATOR_HOST="localhost:8080"
所以我运行
export FIRESTORE_EMULATOR_HOST="localhost:8080"
然后
firebase emulators:start
它仍然从生产中获取数据。事实上,如果我断开互联网连接,测试将不会 运行!
我不知道为什么要检查
console.log(process.env.FIRESTORE_EMULATOR_HOST); // I expect, it will be will be "localhost:8080"
console.log(process.env.FUNCTIONS_EMULATOR); // I expect, it will be "true"
但我会得到两个值的 undefined
,就像这样
看完后github issue in here。我终于找到解决办法了!
首先,在您的 package.json 中,编写您的测试脚本。我的脚本是这样的
"scripts": {
"test-security-rules": "mocha -r ts-node/register src/tests/firestore_security_rules_tests --recursive --extension .test.ts --timeout 60000 --exit",
"test-cloud-functions": "mocha -r ts-node/register src/tests/cloud_function_tests --recursive --extension .test.ts --timeout 60000 --exit"
}
关闭模拟器,不要 运行 firebase emulators:start
.但执行
firebase emulators:exec "npm run test-cloud-functions"
然后如果你打印
console.log(process.env.FIRESTORE_EMULATOR_HOST);
该值将不再是未定义的,但在我的情况下它将是 "localhost:8080"
这里是 documentation 关于 exec
更新到最新的 firestore 模拟器后 (v1.11.14.jar)
我想我找到了这个解决方案
- 运行 你的模拟器像往常一样使用
firebase emulators:start
- 在您的终端中,运行
export FIRESTORE_EMULATOR_HOST="localhost:8080"
(对于mac)
set FIRESTORE_EMULATOR_HOST="localhost:8080"
(对于windows)
- 运行你照常考试。
我正在使用
- 节点 14
- firebase 函数测试:0.2.3
- firebase-admin: 9.6.0
- firebase 函数:3.13.2
- firebase 工具:9.10.0
我正在尝试对预定的云功能执行单元测试。我的云函数是这样的
export const deleteExpiredEvents = functions
.pubsub.schedule("0 0 * * *")
.timeZone("Asia/Jakarta")
.onRun(async (context) => {
// delete expired events
});
我这样测试上面的功能
import * as admin from "firebase-admin";
import * as firebase from "firebase-functions-test";
const test = firebase({
databaseURL: "https://xxxx.firebaseio.com",
projectId: projectID,
}, "./service-account.json");
const db = admin.initializeApp().firestore();
beforeEach( async () => {
// create dummy expired event
await db.doc(`events/${event1.eventID}`).set(event1);
await db.doc(`events/${event2.eventID}`).set(event2);
await db.doc(`events/${event3.eventID}`).set(event3);
});
it("should not delete events that not expired", async () => {
const wrap = test.wrap(myFunctions.deleteExpiredEvents);
const context = {};
wrap(context); // execute function
const querySnapshot = await db.collection("events").get();
querySnapshot.docs.forEach((snapshot) => console.log(snapshot.data().eventID));
// the rest of my code test ....
});
正如您从上面的代码中看到的,在 before
块中,我尝试创建虚拟事件数据,因此我希望我的 firestore 模拟器将填充这 3 个虚拟事件数据。
然后在 it
块中,我尝试获取所有事件,然后 console.log
所有 eventID
s
我预计我将从之前在 before
块中创建的 firestore 模拟器获得 3 个事件,但我不知道为什么我获得 74 个事件(而不是仅仅 3 个),它来自 firestore生产数据,不是来自 firestore 模拟器
我相信我在执行测试时已经 运行 firebase emulators:start
、firestore、函数和 pubsub 模拟器 运行ning。
为什么我在模拟器启动后仍然从生产中获取 firestore 数据?
我尝试从这里阅读文档:https://firebase.google.com/docs/emulator-suite/connect_firestore
据说:
The Firebase Admin SDKs automatically connect to the Cloud Firestore emulator when the FIRESTORE_EMULATOR_HOST environment variable is set:
export FIRESTORE_EMULATOR_HOST="localhost:8080"
所以我运行
export FIRESTORE_EMULATOR_HOST="localhost:8080"
然后
firebase emulators:start
它仍然从生产中获取数据。事实上,如果我断开互联网连接,测试将不会 运行!
我不知道为什么要检查
console.log(process.env.FIRESTORE_EMULATOR_HOST); // I expect, it will be will be "localhost:8080"
console.log(process.env.FUNCTIONS_EMULATOR); // I expect, it will be "true"
但我会得到两个值的 undefined
,就像这样
看完后github issue in here。我终于找到解决办法了!
首先,在您的 package.json 中,编写您的测试脚本。我的脚本是这样的
"scripts": {
"test-security-rules": "mocha -r ts-node/register src/tests/firestore_security_rules_tests --recursive --extension .test.ts --timeout 60000 --exit",
"test-cloud-functions": "mocha -r ts-node/register src/tests/cloud_function_tests --recursive --extension .test.ts --timeout 60000 --exit"
}
关闭模拟器,不要 运行 firebase emulators:start
.但执行
firebase emulators:exec "npm run test-cloud-functions"
然后如果你打印
console.log(process.env.FIRESTORE_EMULATOR_HOST);
该值将不再是未定义的,但在我的情况下它将是 "localhost:8080"
这里是 documentation 关于 exec
更新到最新的 firestore 模拟器后 (v1.11.14.jar)
我想我找到了这个解决方案
- 运行 你的模拟器像往常一样使用
firebase emulators:start
- 在您的终端中,运行
export FIRESTORE_EMULATOR_HOST="localhost:8080"
(对于mac)
set FIRESTORE_EMULATOR_HOST="localhost:8080"
(对于windows)
- 运行你照常考试。