如何在Firebase云功能测试中模拟FCM admin.messaging()。sendToDevice()的实现

时间:2019-07-15 08:00:11

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

我无法在Typescript中为Firebase Cloud Functions模拟Firebase Messaging函数。我正在使用firebase-functions-test的Companion SDK来构建docs中提到的在线测试。我正在使用笑话模拟来模拟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)=>无效,拒绝:(原因?:任何)=>无效)=>无效'

我要测试的代码:


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 个答案:

答案 0 :(得分:1)

查看您的代码,有几件事丢失/不正确:

  1. 更改jest.spyOn(admin.messaging(),'sendToDevice');到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);
  });