[英]How to mock implementation for FCM admin.messaging().sendToDevice() in Firebase Cloud Functions Tests
[英]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.