代码之家  ›  专栏  ›  技术社区  ›  Jürgen Brandstetter

如何建立适合JS开发的firebase firestore和cloud函数测试

  •  0
  • Jürgen Brandstetter  · 技术社区  · 6 年前

    根据以下firebase团队的google I/O(2019)帖子,新模拟器允许我们结合firebase/数据库和云功能来完全模拟firebase服务器代码。这也意味着我们应该能够为它编写测试。

    发布了一个全新的云功能模拟器 与云Firestore模拟器通信。所以如果你想建造 数据返回到数据库,您可以编写代码并测试整个流 Firebase Blog Entry )

    我可以找到多个资源来查找/描述每个单独的模拟,但不能全部放在一起

    1. Unit Testing Cloud Function
    2. Emulate Database writes
    3. Emulate Firestore writes
    1 回复  |  直到 5 年前
        1
  •  7
  •   Jürgen Brandstetter    5 年前

    要为允许您模拟读/写和设置测试数据的云函数设置测试环境,必须执行以下操作。请记住,这实际上是模拟/触发了云功能。因此,在写入firestore之后,需要稍等云函数完成写入/处理,然后才能读取断言数据。

    下面是一个代码如下的回购示例: https://github.com/BrandiATMuhkuh/jaipuna-42-firebase-emulator

    先决条件

    我假设此时您已经设置了一个firebase项目,其中包含一个functions文件夹和 index.js functions/test 文件夹。如果您没有使用项目设置 firebase init 设置项目。

    再进行

    首先添加/安装以下依赖项: mocha @firebase/testing , firebase-functions-test firebase-functions , firebase-admin , firebase-tools 进入 functions/package.json 不是根文件夹。

    jaipuna-42-firebase-emulator 姓名

    你用你自己的很重要 project-id . 一定是 你自己的项目必须存在。假身份证行不通。所以搜索所有 在下面的代码中替换为 项目id

    示例云函数的index.js

    // functions/index.js
    
    const functions = require("firebase-functions");
    const admin = require("firebase-admin");
    
    // init the database
    admin.initializeApp(functions.config().firebase);
    let fsDB = admin.firestore();
    
    const heartOfGoldRef = admin
        .firestore()
        .collection("spaceShip")
        .doc("Heart-of-Gold");
    
    exports.addCrewMemeber = functions.firestore.document("characters/{characterId}").onCreate(async (snap, context) => {
        console.log("characters", snap.id);
    
        // before doing anything we need to make sure no other cloud function worked on the assignment already
        // don't forget, cloud functions promise an "at least once" approache. So it could be multiple
        // cloud functions work on it. (FYI: this is called "idempotent")
    
        return fsDB.runTransaction(async t => {
            // Let's load the current character and the ship
            const [characterSnap, shipSnap] = await t.getAll(snap.ref, heartOfGoldRef);
    
            // Let's get the data
            const character = characterSnap.data();
            const ship = shipSnap.data();
    
            // set the crew members and count
            ship.crew = [...ship.crew, context.params.characterId];
            ship.crewCount = ship.crewCount + 1;
    
            // update character space status
            character.inSpace = true;
    
            // let's save to the DB
            await Promise.all([t.set(snap.ref, character), t.set(heartOfGoldRef, ship)]);
        });
    });
    
    
    

    mocha测试文件index.test.js

    // functions/test/index.test.js
    
    
    // START with: yarn firebase emulators:exec "yarn test --exit"
    // important, project ID must be the same as we currently test
    
    // At the top of test/index.test.js
    require("firebase-functions-test")();
    
    const assert = require("assert");
    const firebase = require("@firebase/testing");
    
    // must be the same as the project ID of the current firebase project.
    // I belive this is mostly because the AUTH system still has to connect to firebase (googles servers)
    const projectId = "jaipuna-42-firebase-emulator";
    const admin = firebase.initializeAdminApp({ projectId });
    
    beforeEach(async function() {
        this.timeout(0);
        await firebase.clearFirestoreData({ projectId });
    });
    
    async function snooz(time = 3000) {
        return new Promise(resolve => {
            setTimeout(e => {
                resolve();
            }, time);
        });
    }
    
    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);
    
        // wait until the CF is done.
        await snooz();
    
        // check if the crew size has change
        const heart = await heartOfGold.get();
        const trillian = await trillianRef.get();
    
        console.log("heart", heart.data());
        console.log("trillian", trillian.data());
    
        // 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");
    });
    
    
    

    运行测试

    functions 文件夹和写入 yarn firebase emulators:exec "yarn test --exit" . 此命令也可以在您的CI管道中使用

    如果一切正常,您应该看到以下输出

      √ Add Crew Members (5413ms)
    
      1 passing (8S)