【问题标题】:How to test `functions.https.onCall` firebase cloud functions locally?如何在本地测试`functions.https.onCall`firebase云功能?
【发布时间】:2018-11-25 19:52:11
【问题描述】:

我似乎无法在 Firebase Documentation 中找到解决方案。

我想在本地测试我的functions.https.onCall 函数。是否可以使用 shell 或以某种方式将我的客户端(启用 firebase SDK)连接到本地服务器?

我想避免每次只为了测试对我的onCall 函数的更改而进行部署。


我的代码

功能:

exports.myFunction = functions.https.onCall((data, context) => {
  // Do something
});

客户:

const message = { message: 'Hello.' };

firebase.functions().httpsCallable('myFunction')(message)
  .then(result => {
    // Do something //
  })
  .catch(error => {
    // Error handler //
  });

【问题讨论】:

    标签: firebase google-cloud-functions


    【解决方案1】:

    对于本地,您必须调用(在 firebase.initializeApp 之后)

    firebase.functions().useFunctionsEmulator('http://localhost:5000') 
    

    【讨论】:

    • 太棒了!当我可以访问代码时,我会试试这个。顺便说一句,这是新添加的功能吗?
    • 这行得通!我即将进入一个永无止境的部署-编辑-部署循环......这应该在文档指南中。谢谢。
    • 这项工作只是确保您访问正确的端口,它可能并不总是:5000,-谢谢!
    • 这在我的情况下不起作用。 functions().useFunctionsEmulator 没有方法。有什么帮助吗?
    • 我的进口:从'firebase/app'导入firebase; import 'firebase/functions' // 重要
    【解决方案2】:

    Callables 只是具有特定格式的 HTTPS 函数。您可以test just like a HTTPS function,但您必须编写代码以将协议作为defined in the documentation 传递给它。

    【讨论】:

      【解决方案3】:

      有一个简单的技巧,您可以如何简化onCall 功能测试。只需将 onCall 函数回调声明为本地函数并对其进行测试:

      export const _myFunction = (data, context) => { // <= call this on your unit tests
        // Do something
      }
      
      exports.myFunction = functions.https.onCall(_myFunction);
      

      现在您可以使用您在函数调用中定义的输入,使用普通函数改变所有情况。

      【讨论】:

      • 非常感谢这个想法。老实说,我觉得 Firebase callables 的测试人体工程学是可恶的......为什么我需要存根/模拟 Firebase 内部的这么多元素只是为了产生一个有效的测试?我只想检查值和值。您的解决方案的缺点是无法测试 Firebase 可调用的包装结果,但我会接受。
      • 更进一步,您可以使用 Firebase 的模拟器。我也一直在为这些目的开发 ts-mock-firebase -library。目前项目一直处于非活动状态,主要是因为谷歌在自己的模拟器上取得了进展。
      • 我可以评论一下,这里答案中的onCall应该是onRequest。感谢您的技巧,它似乎有效。什么任务
      【解决方案4】:

      虽然官方 Firebase Cloud Function 文档尚未更新,但您现在可以将 firebase-functions-test 与 onCall 函数一起使用。

      你可以看到example in their repository。

      我已经成功地使用 jest 测试了我的 TypeScript 函数,这是一个简短的示例。这里有一些特殊之处,例如导入顺序,因此请务必阅读文档 :-)

      /* functions/src/test/index.test.js */
      /* dependencies: Jest and jest-ts */
      
      const admin = require("firebase-admin");
      jest.mock("firebase-admin");
      admin.initializeApp = jest.fn(); // stub the init (see docs)
      const fft = require("firebase-functions-test")();
      
      import * as funcs from "../index";
      
      // myFunc is an https.onCall function
      describe("test myFunc", () => {
        // helper function so I can easily test different context/auth scenarios
        const getContext = (uid = "test-uid", email_verified = true) => ({
          auth: {
            uid,
            token: {
              firebase: {
                email_verified
              }
            }
          }
        });
        const wrapped = fft.wrap(funcs.myFunc);
      
        test("returns data on success", async () => {
          const result = await wrapped(null, getContext());
          expect(result).toBeTruthy();
        });
      
        test("throws when no Auth context", async () => {
          await expect(wrapped(null, { auth: null })).rejects.toThrow(
            "No authentication context."
          );
        });
      });
      

      【讨论】:

        【解决方案5】:

        您应该首先检查开发环境,然后将您的函数指向本地模拟器。
        对于 JS:

        //after firebase init
        if (window.location.host.includes("localhost") ||
            window.location.host.includes("127.0.0.1")
        ) {
            firebase
              .app()
              .functions()  //add location here also if you're mentioning location while invoking function()
              .useFunctionsEmulator("http://localhost:5001");
          }
        

        或者,如果您不创建 firebase 实例,则

        //after firebase init
        if (window.location.host.includes("localhost") || 
           window.location.host.includes("127.0.0.1")
        ) {
            firebase
              .functions()
              .useFunctionsEmulator("http://localhost:5001");
          }
        

        或从后端 (node.js) 提供页面时:

        //after firebase init
        if (process.env.NODE_ENV === 'development') {
          firebase.functions().useFunctionsEmulator('http://localhost:5001');
        }
        

        【讨论】:

          【解决方案6】:

          如果您使用 angularfire,请将其添加到您的 app.module

          {
            provide: FirestoreSettingsToken,
            useValue: environment.production
              ? undefined
              : {
                  host: "localhost:5002",
                  ssl: false
                }
          }
          

          【讨论】:

            猜你喜欢
            • 2020-10-25
            • 2020-12-16
            • 2021-07-01
            • 1970-01-01
            • 2022-12-17
            • 2020-10-02
            • 2017-08-03
            • 2020-10-09
            相关资源
            最近更新 更多