如何在 Firebase Cloud Functions 测试中模拟 FCM admin.messaging().sendToDevice() 的实现
Posted
技术标签:
【中文标题】如何在 Firebase Cloud Functions 测试中模拟 FCM admin.messaging().sendToDevice() 的实现【英文标题】:How to mock implementation for FCM admin.messaging().sendToDevice() in Firebase Cloud Functions Tests 【发布时间】:2019-11-23 21:45:09 【问题描述】:我无法在 Typescript for Firebase Cloud Functions 中模拟 Firebase 消息传递函数。我正在使用firebase-functions-test Companion SDK 来构建docs 中提到的在线测试。我正在使用 jest mocks 来模拟 admin.messaging().sendToDevice
函数。
const fcmMock = jest.spyOn(admin.messaging(),'sendToDevice');
fcmMock.mockImplementation(async (registrationToken: string | string[], payload: admin.messaging.MessagingPayload, options?: admin.messaging.MessagingOptions)=>
console.log('FCM Mock called with message: '+payload.notification+'\nToken ids:'+registrationToken);
return new Promise<admin.messaging.MessagingDevicesResponse>(undefined);
);
因为返回类型对象MessagingDevicesResponse>(undefined)
需要一个复杂的参数,所以运行它会得到以下错误:
'undefined' 类型的参数不能分配给 '(resolve: (value?: MessagingDevicesResponse | PromiseLike | undefined) => void, reject: (reason?: any) => void) => void' 类型的参数.
我要测试的代码:
export async function cleanupToken(response: admin.messaging.MessagingDevicesResponse, userDataSnapshot:FirebaseFirestore.DocumentSnapshot)
// For each notification we check if there was an error.
if(response.results.length>0)
const error = response.results[0].error;
if (error)
// Cleanup the tokens who are not registered anymore.
// Error Codes: https://firebase.google.com/docs/cloud-messaging/send-message#admin_sdk_error_reference
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered')
// Some Logic here to cleanup the token and mark the user
【问题讨论】:
【参考方案1】:查看您的代码有一些缺失/不正确的地方:
-
更改 jest.spyOn(admin.messaging(),'sendToDevice'); to jest.spyOn(admin,'sendToDevice');
传入模拟对象,在本例中是响应和快照
// A fake response object, with a send to test the response
const res =
send: (response) =>
expect(response).toBe("Hello from Firebase!");
done();
;
//how to create a datasnapshot. Takes in 2 parameters, the object and the reference path
const userDataSnapshot = test.database.makeDataSnapshot(Object,'ref/to-the/path');
您不会在开玩笑的测试用例中返回承诺,而是使用开玩笑的测试方法(在这种情况下是预期的)。
通常开玩笑的测试(在这种情况下是预期的)可以在函数中完成,但我们在响应中执行它,因为这是回调,因此它发生在最后。
李>你的测试用例应该是这样的:
describe('testing jest functions',() =>
let index,adminStub;
//setup test enviroment
beforeAll(() =>
adminStub = jest.spyOn(admin, "initializeApp");
index = require('./index');
return;
);
//tear down
afterAll(() =>
adminStub.mockRestore();
testEnv.cleanup();
);
it('test cleanupToken function', (done) =>
const res =
send: (response) =>
//assuming you use response.send in your actual code you can test it
expect(response).toBe("Hello from Firebase!");
done();
;
const userDataSnapshot = test.database.makeDataSnapshot(Object,'ref/to-the/path');
index.cleanupToken(res,userDataSnapshot);
);
【讨论】:
如果它回答了您的问题,您能否将其设为已接受的答案。谢谢以上是关于如何在 Firebase Cloud Functions 测试中模拟 FCM admin.messaging().sendToDevice() 的实现的主要内容,如果未能解决你的问题,请参考以下文章
如何将我的 Firebase 实时数据库转移到 Firebase Cloud Firestore
如何在 Firebase Cloud Functions 中确认 PubSub 消息?
Firebase Cloud Functions 如何确认 Cloud pub/sub
如何从 Cloud Function 调用其他 Cloud Firebase Functions