簡體   English   中英

如何在 Firebase 雲函數中模擬輔助函數?

[英]How to mock helper functions in Firebase Cloud Functions?

我目前正在探索 Firebase Cloud Functions 中的單元測試,並遇到了一個似乎很頻繁但官方文檔未涵蓋的用例。

在為各種進程和觸發器編寫 Cloud Functions 時,我們通常會使用單獨的輔助函數來幫助我們編寫更多可重用的代碼。 例如:

// index.ts
import * as functions from "firebase-functions";

function add(num1: number, num2: number) {
    return num1 + num2;
}

exports.getSum = functions.https.onCall((data, context) => {
    return {
        result: add(data.num1, data.num2)
    }
})

當我現在想測試getSum時,我必須將它導入我的測試文件並做出斷言。 但是,這是我遇到問題的地方:

如何斷言add已在getSum中調用? 或者更好:我如何模擬add

到目前為止,我發現的唯一解決方法是導出add ,然后修改代碼以調用this.add而不是像這樣add

// index.ts
import * as functions from "firebase-functions";

export function add(num1: number, num2: number) {
    return num1 + num2;
}

exports.getSum = functions.https.onCall((data, context) => {
    return {
        // @ts-ignore
        result: this.add(data.num1, data.num2)
    }
})

然而這個解決方案並不理想,因為我 1. 不能保證this不是未定義的(這也是我需要// @ts-ignore它的原因)和 2. 需要修改原始代碼以使測試工作。

有沒有辦法在不修改功能代碼的情況下完成這項工作? 測試這些輔助函數的任何最佳實踐? 先感謝您!

這是我用於解決方法的完整單元測試代碼:

// index.unit.test.ts
const testEnvironment = require("firebase-functions-test")(
  {
    databaseURL: "",
        storageBucket: "",
        projectId: "",
    },
    "credentials.json"
  );
  const myFunctions = require("../src/index");


describe("getSum", () => {
    let wrapper: any, group: any;

    beforeAll(() => {
        group = myFunctions.addition
        wrapper = testEnvironment.wrap(group.getSum);
    });

    it("adds two numbers", () => {    
        group.add = jest.fn()
    
        wrapper({ num1: 2, num2: 2})

        expect(group.add).toHaveBeenCalled()
    });
});

您可以使用rewire package 來模擬add function 而無需修改代碼。 為簡單起見,我將使用離線模式來測試代碼。 只是為了演示如何模擬add function。

例如

index.ts

import * as functions from "firebase-functions";

function add(num1: number, num2: number) {
  return num1 + num2;
}

exports.getSum = functions.https.onCall((data, context) => {
  return {
    result: add(data.num1, data.num2),
  };
});

index.unit.test.ts

const testEnvironment = require("firebase-functions-test")();
const rewire = require("rewire");

describe("getSum", () => {
  it("adds two numbers", () => {
    const mod = rewire("./");
    const mAdd = jest.fn().mockReturnValueOnce(666);
    mod.__set__("add", mAdd);
    const wrapper = testEnvironment.wrap(mod.getSum);
    const actual = wrapper({ num1: 2, num2: 2 });
    console.log(actual);
    expect(actual).toEqual({ result: 666 });
    expect(mAdd).toBeCalledWith(2, 2);
  });
});

npm 腳本:

"test:cjs": "ts-node -O '{\"module\":\"commonjs\"}' node_modules/jest/bin/jest.js"

使用覆蓋率報告運行單元測試

npm run test:cjs -- --coverage ./index.unit.test.ts

單元測試結果:

{"severity":"WARNING","message":"Warning, FIREBASE_CONFIG and GCLOUD_PROJECT environment variables are missing. Initializing firebase-admin will fail"}
 PASS  stackoverflow/65763396/index.unit.test.ts
  getSum
    ✓ adds two numbers (433ms)

  console.log
    { result: 666 }

      at Object.<anonymous> (stackoverflow/65763396/index.unit.test.ts:11:13)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.316s, estimated 3s

package 版本:

"devDependencies": {
    "@types/jest": "^25.2.1",
    "firebase-functions-test": "^0.2.3",
    "jest": "^25.5.4",
    "rewire": "^5.0.0",
    "ts-jest": "^25.5.1",
    "ts-node": "^9.1.1",
    "typescript": "^3.9.2"
  },
  "dependencies": {
    "firebase": "^7.4.0",
    "firebase-admin": "^9.4.2",
    "firebase-functions": "^3.13.1"
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM