根据以下Firebase团队的google I / O(2019)帖子,新的模拟器可让我们结合使用Firebase /数据库和云功能来完全模拟我们的Firebase服务器代码。这也意味着我们应该能够为此编写测试。
我们发布了全新的Cloud Functions模拟器,该模拟器还可以 与Cloud Firestore模拟器进行通信。所以如果你想建造 触发Firestore文档更新并写入的函数 数据返回数据库,您可以编码并测试整个流程 在笔记本电脑上本地(来源:Firebase Blog Entry)
我可以找到多个资源来查找/描述每个单独的模拟,但没有全部结合在一起
答案 0 :(得分:3)
对于那些努力测试Firestore触发器的人,我创建了一个示例存储库,希望可以对其他人有所帮助。
https://github.com/benwinding/example-jest-firestore-triggers
它使用玩笑和本地Firebase模拟器。
答案 1 :(得分:2)
要为云功能设置测试环境,以允许您模拟读/写和设置测试数据,您必须执行以下操作。
我现在假设您已经建立了一个Firebase项目,其中包含一个functions文件夹和index.js
。测试稍后将放在functions/test
文件夹中。如果您没有项目设置,请使用firebase init
来设置项目。
首先添加/安装以下依赖项:mocha
,@firebase/testing
,firebase-functions-test
,firebase-functions
,firebase-admin
,firebase-tools
firebase setup:emulators:database
firebase setup:emulators:firestore
firebase emulators:start
启动模拟器这时,您应该正在运行数据库和Firestore模拟器。现在我们可以对其进行读写。
// functions/index.js
const fbInit = require("./ainitFb");
let admin = fbInit.getAdmin();
const functions = require("firebase-functions");
exports.addCrewMemeber = functions.firestore
.document("characters/{characterId}")
.onCreate(async (characterSnap, context) => {
const heartOfGold = admin
.firestore()
.collection("spaceShip")
.doc("Heart-of-Gold");
const heartData = (await heartOfGold.get()).data();
await heartOfGold.set({
crew: [...heartData.crew, context.params.characterId],
crewCount: heartData.crewCount + 1,
});
// Update the characters to be in space
return characterSnap.ref.update({ inSpace: true });
});
您会发现我没有直接从admin
导入firebase-admin
。而是从require("./ainitFb")
开始。之所以这样做,是因为我们需要对管理员进行打桩,并将新管理员指向模拟器。
// functions/aniniFb.js
exports.initializeMockApp = function(mock) {
admin = mock;
};
exports.initializeApp = function() {
if (!admin) {
admin = require("firebase-admin");
admin.initializeApp();
}
};
exports.getAdmin = function() {
return global.admin;
};
exports.admin = (inneradmin => {
return inneradmin;
})(
global.admin,
);
// functions/test/test.js
const assert = require("assert");
const projectId = "dummy";
const firebase = require("@firebase/testing");
const admin = firebase.initializeAdminApp({ projectId, databaseName: projectId });
const test = require("firebase-functions-test")({ projectId, databaseName: projectId });
const fbInit = require("../ainitFb");
// this will inject the mocked admin
fbInit.initializeMockApp(admin);
// load this only after you ran 'initializeMockApp'
const myFunctions = require("../index.js");
// Create a simple document snapshot
// I did that because currently using test.firestore.makeDocumentSnapshot() is not working
// For some reasons it says the firebase db can't be reached, while it's actually running
function makeDocumentSnapshot(data, ref) {
return {
id: ref.id,
data: () => data,
ref,
};
}
beforeEach(async function() {
// we remove the timeout as the default is 2sec which is often too short to also start the emulators
this.timeout(0);
// Clear the database between tests
await firebase.clearFirestoreData({ projectId });
});
it("Add Crew Members", async function() {
this.timeout(0);
const heartOfGold = admin
.firestore()
.collection("spaceShip")
.doc("Heart-of-Gold");
const trillianRef = admin
.firestore()
.collection("characters")
.doc("Trillian");
// init crew members of the Heart of Gold
await heartOfGold.set({
crew: [],
crewCount: 0,
});
// save the character Trillian to the DB
const trillianData = { name: "Trillian", inSpace: false };
await trillianRef.set(trillianData);
// Add Trillian to the Heart of Gold
const trillianSnap = makeDocumentSnapshot(trillianData, trillianRef);
const addCrewMemeber = test.wrap(myFunctions.addCrewMemeber);
await addCrewMemeber(trillianSnap, { params: { characterId: "Trillian" } });
// check if the crew size has change
const heart = await heartOfGold.get();
const trillian = await trillianRef.get();
// at this point the Heart of Gold has one crew member and trillian is in space
assert.deepStrictEqual(heart.data().crewCount, 1, "Crew Members");
assert.deepStrictEqual(trillian.data().inSpace, true, "In Space");
});
要运行测试,我们可以简单地从mocha
开始摩卡(如果已全局安装),或者从yarn mocha
(如果通过yarn
在本地安装)开始。
如果一切正常,您应该会看到以下输出
√ Add Crew Members (189ms)
1 passing (223ms)
要在CI系统上运行相同的代码,需要确保已启动仿真器,然后才能运行测试。只需使用firebase emulators:exec
命令即可完成。例如firebase emulators:exec "mocha --exit"
。请不要忘记--exit
,否则摩卡咖啡可能无法完成,并且CI运行程序也不会停止。另外,如果您在运行/启动测试或仿真器时遇到麻烦,则可能是在错误的文件夹中初始化了它们。我使用此yarn firebase emulators:exec --only database,firestore "yarn mocha functions --exit"
来解决摩卡外观在错误文件夹中的问题。