【问题标题】:How to mock implementation for FCM admin.messaging().sendToDevice() in Firebase Cloud Functions Tests如何在 Firebase Cloud Functions 测试中模拟 FCM admin.messaging().sendToDevice() 的实现
【发布时间】: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&gt;(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
                }
            }
        }
    }
}

【问题讨论】:

    标签: typescript firebase unit-testing firebase-cloud-messaging google-cloud-functions


    【解决方案1】:

    查看您的代码有一些缺失/不正确的地方:

    1. 更改 jest.spyOn(admin.messaging(),'sendToDevice'); to jest.spyOn(admin,'sendToDevice');
    2. 传入模拟对象,在本例中是响应和快照

      // 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');
      
    3. 您不会在开玩笑的测试用例中返回承诺,而是使用开玩笑的测试方法(在这种情况下是预期的)。

    4. 通常开玩笑的测试(在这种情况下是预期的)可以在函数中完成,但我们在响应中执行它,因为这是回调,因此它发生在最后。

      李>

    你的测试用例应该是这样的:

    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);
      });
    

    【讨论】:

    • 如果它回答了您的问题,您能否将其设为已接受的答案。谢谢
    猜你喜欢
    • 2018-09-10
    • 2021-04-22
    • 2018-03-05
    • 1970-01-01
    • 2021-11-30
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多