Firebase 功能:离线测试时如何存根 firebase-admin 功能
Firebase functions: How to stub firebase-admin functions when testing offline
尝试按照此处的文档来测试 Firease 功能https://firebase.google.com/docs/functions/unit-testing,但不清楚如何使用 sinon 存根 firebase-admin.database。我在下面提供了此错误的函数代码、mocha 测试和控制台输出。从错误输出看来,当函数被调用时 admin.initializeApp();
正在被调用,但在测试中事先没有被正确存根。
函数代码:
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
// add new users to the database
exports.account = functions.auth.user().onCreate(event => {
// console.log('addAccount()', event);
const { uid, providerData } = event;
const email = providerData[0].email;
return admin
.database()
.ref('/users/' + uid)
.set({ email, uid });
});
测试重现问题:
const sinon = require('sinon');
const chai = require('chai');
const assert = chai.assert;
const admin = require('firebase-admin');
const test = require('firebase-functions-test')();
describe('Cloud Functions', () => {
let myFunctions, adminInitStub, adminDatabaseStub;
before(() => {
adminInitStub = sinon.stub(admin, 'initializeApp');
adminDatabaseStub = sinon.stub(admin, 'database');
myFunctions = require('../index');
});
after(() => {
adminInitStub.restore();
adminDatabaseStub.restore();
test.cleanup();
});
describe('account', () => {
it('should write to /users', () => {
// given
const setParam = { email: 'test@test.com', uid: 1234 };
const setStub = sinon.stub();
setStub.withArgs(setParam).returns(true);
const refStub = sinon.stub();
refStub.withArgs('/users/1234').returns({ set: setStub });
adminDatabaseStub.returns({ ref: refStub });
const wrapped = test.wrap(myFunctions.account);
const event = {
uid: 1234,
providerData: [{
email: 'test@test.com'
}]
};
// when
const actual = wrapped(event);
// then
return assert.equal(actual, true);
});
});
});
控制台出错
Cloud Functions
account
1) should write to /users
0 passing (53ms)
1 failing
1) Cloud Functions
account
should write to /users:
Error: The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.
at FirebaseAppError.FirebaseError [as constructor] (node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseAppError (node_modules/firebase-admin/lib/utils/error.js:122:28)
at FirebaseNamespaceInternals.app (node_modules/firebase-admin/lib/firebase-namespace.js:101:19)
at FirebaseNamespace.app (node_modules/firebase-admin/lib/firebase-namespace.js:402:30)
at FirebaseNamespace.ensureApp (node_modules/firebase-admin/lib/firebase-namespace.js:418:24)
at FirebaseNamespace.fn (node_modules/firebase-admin/lib/firebase-namespace.js:280:30)
at Function.exports.account.functions.auth.user.onCreate.event [as run] (index.js:65:21)
at wrapped (node_modules/firebase-functions-test/lib/main.js:68:30)
at Context.it (test/index.test.js:45:22)
解决方案
将 adminDatabaseStub.get()
更新为 return 一个 getterFn()
函数,然后 return 更新 ref
存根。谢谢@hiranya-jayathilaka
之前
adminDatabaseStub.returns({ ref: refStub });
之后
adminDatabaseStub.get(function getterFn() {
return () => {
return { ref: refStub };
};
});
admin.database
存根必须 return 一个可调用对象才能使 admin.database()
工作。 admin.database
在 SDK 中实际上是一个 属性 getter。有关示例和相关讨论,请参阅 https://github.com/firebase/firebase-admin-node/issues/122#issuecomment-339586082。
尝试按照此处的文档来测试 Firease 功能https://firebase.google.com/docs/functions/unit-testing,但不清楚如何使用 sinon 存根 firebase-admin.database。我在下面提供了此错误的函数代码、mocha 测试和控制台输出。从错误输出看来,当函数被调用时 admin.initializeApp();
正在被调用,但在测试中事先没有被正确存根。
函数代码:
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
// add new users to the database
exports.account = functions.auth.user().onCreate(event => {
// console.log('addAccount()', event);
const { uid, providerData } = event;
const email = providerData[0].email;
return admin
.database()
.ref('/users/' + uid)
.set({ email, uid });
});
测试重现问题:
const sinon = require('sinon');
const chai = require('chai');
const assert = chai.assert;
const admin = require('firebase-admin');
const test = require('firebase-functions-test')();
describe('Cloud Functions', () => {
let myFunctions, adminInitStub, adminDatabaseStub;
before(() => {
adminInitStub = sinon.stub(admin, 'initializeApp');
adminDatabaseStub = sinon.stub(admin, 'database');
myFunctions = require('../index');
});
after(() => {
adminInitStub.restore();
adminDatabaseStub.restore();
test.cleanup();
});
describe('account', () => {
it('should write to /users', () => {
// given
const setParam = { email: 'test@test.com', uid: 1234 };
const setStub = sinon.stub();
setStub.withArgs(setParam).returns(true);
const refStub = sinon.stub();
refStub.withArgs('/users/1234').returns({ set: setStub });
adminDatabaseStub.returns({ ref: refStub });
const wrapped = test.wrap(myFunctions.account);
const event = {
uid: 1234,
providerData: [{
email: 'test@test.com'
}]
};
// when
const actual = wrapped(event);
// then
return assert.equal(actual, true);
});
});
});
控制台出错
Cloud Functions
account
1) should write to /users
0 passing (53ms)
1 failing
1) Cloud Functions
account
should write to /users:
Error: The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.
at FirebaseAppError.FirebaseError [as constructor] (node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseAppError (node_modules/firebase-admin/lib/utils/error.js:122:28)
at FirebaseNamespaceInternals.app (node_modules/firebase-admin/lib/firebase-namespace.js:101:19)
at FirebaseNamespace.app (node_modules/firebase-admin/lib/firebase-namespace.js:402:30)
at FirebaseNamespace.ensureApp (node_modules/firebase-admin/lib/firebase-namespace.js:418:24)
at FirebaseNamespace.fn (node_modules/firebase-admin/lib/firebase-namespace.js:280:30)
at Function.exports.account.functions.auth.user.onCreate.event [as run] (index.js:65:21)
at wrapped (node_modules/firebase-functions-test/lib/main.js:68:30)
at Context.it (test/index.test.js:45:22)
解决方案
将 adminDatabaseStub.get()
更新为 return 一个 getterFn()
函数,然后 return 更新 ref
存根。谢谢@hiranya-jayathilaka
之前
adminDatabaseStub.returns({ ref: refStub });
之后
adminDatabaseStub.get(function getterFn() {
return () => {
return { ref: refStub };
};
});
admin.database
存根必须 return 一个可调用对象才能使 admin.database()
工作。 admin.database
在 SDK 中实际上是一个 属性 getter。有关示例和相关讨论,请参阅 https://github.com/firebase/firebase-admin-node/issues/122#issuecomment-339586082。