如何在 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&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
                
            
        
    

【问题讨论】:

【参考方案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

如何将我的 Firebase 实时数据库转移到 Firebase Cloud Firestore

如何在 PC 上本地测试 Cloud Functions for Firebase