【问题标题】:How to call a firebase functions from a unit test using Firebase Emulators?如何使用 Firebase 模拟器从单元测试中调用 firebase 函数?
【发布时间】:2021-11-10 02:31:38
【问题描述】:

我正在运行 firebase 模拟器。

如果允许用户(取决于数据库中的值),我的应用程序可以调用可以创建自定义用户声明的 firebase 云函数

我正在尝试调用该函数:


import * as firebase from '@firebase/testing';
import * as fs from 'fs';

const app = firebase.initializeTestApp({
  databaseName: 'mydb',
  auth: {
    uid: 'useruid'
  },
});

describe('Firebase Functions', () => {
  beforeEach(async () => {
    await firebase.loadDatabaseRules({
      databaseName: 'mydb',
      rules: fs.readFileSync('database.rules.json', 'utf8'),
    });
  });

  afterAll(async () => {
    await Promise.all(firebase.apps().map((app) => app.delete()));
  });

  const cloudfunction = app.functions().httpsCallable('cloudfunction')

  it('throws error if user is not authenticated', async () => {
    await firebase.assertFail(cloudfunction())
  })
});


这是抛出一个错误:

错误:错误:预检响应包含无效的 HTTP 状态代码 404

【问题讨论】:

    标签: javascript firebase-authentication google-cloud-functions firebase-tools


    【解决方案1】:

    为此存在firebase-functions-test。这允许您包装您的云函数并直接调用它们,以及为文档更新创建存根。在模拟器的上下文中运行时,firebase-admin SDK 仍然与模拟器交互。基本设置可能如下所示(假设是打字稿):

    // functions/src/test/functions.test.ts
    import {expect} from "chai";
    import "mocha";
    
    import firebaseFunctionTest from "firebase-functions-test";
    import * as cf from "../index";
    
    const projectId = "demo-project";
    const test = firebaseFunctionTest({
      projectId,
    });
    
    after(() => test.cleanup());
    
    describe("cloud functions", () => {
      afterEach(async () => {
        await test.firestore.clearFirestoreData(projectId);
      });
    
      describe("myFunction", () => {
          const myFunction = test.wrap(cf.myFunction);
          // Create mock data with the admin SDK and test function.
      }
    }
    

    在你的package.json你可以放一个类似的脚本。

    "scripts": {
      "test:unit": "mocha -r ts-node/register --timeout 5000 --exit src/**/*.test.ts",
      "test": "npm run build && npx firebase -P demo-project emulators:exec 'npm run test:unit'",
      ...
    }  
    

    您可能还想看看https://github.com/firebase/quickstart-testing/tree/master/unit-test-cloud-functionshttps://firebase.google.com/docs/functions/unit-testing

    【讨论】:

    • 这是为了测试云功能。我想测试调用该函数的 webapp。我不能import * as cf from "../index";,因为云函数是在单独的项目中声明的。
    • 好吧,我误解了。您能否在单独的项目中启动模拟器并连接您要针对该模拟器进行测试的项目?
    • 问题是您不能使用@firebase/testing 库从单元测试中调用在模拟器中运行的云函数。我只是在我的应用程序的单元测试中模拟了我的数据库功能
    【解决方案2】:

    在我看来,您不需要从单元测试中调用 firebase,因为 firebase 是否正常工作不是您的业务,您需要测试您的业务逻辑,这意味着您将模拟该方法调用 firebase 并测试此方法的预期返回值,例如,您可以编写 2 种情况,通知将在没有错误的情况下发送,第二种情况,如果 firebase 服务将返回失败,对于这 2 种情况,您的代码应该具有适当的行为。 测试 firebase 服务将由开发 firebase 的团队完成

    【讨论】:

    • 我正在编写集成测试。我的其他测试已经与使用 Firebase Emulators 模拟的数据库进行交互,为什么不使用呢?我正在测试整个端到端流程,例如,如果用户具有正确的授权,用户可能会单击 ui 中的一个按钮,该按钮调用一个 firebase 函数,该函数会更改数据库中的数据。我可以对每个步骤进行单元测试,但我也想测试整个行为以确保每个步骤之间没有错误。
    • 无论如何你可以模拟firebase方法,我的意思是你可以手动测试firebase,当你构建你的应用程序时,但在开发过程中我认为模拟和测试你的代码更合理,
    • 即使您是 firebase 开发人员,您也应该从 firebase 内部测试 firebase,并且应该从外部应用程序模拟并查看该服务何时返回一些失败或成功的所有情况,您代码应该预期所有情况
    • 否则您想检查您是否正确调用了此服务,但该服务具有库和文档,它是代码的不可检查部分,在单元测试和集成测试中您可以测试你的本地业务逻辑
    • 我明白你的意思,但这并不能解决问题。现在,我将模拟我的函数,但是当 @firebase/testing 适用于数据库时,不支持为云函数调用模拟器是没有意义的。
    猜你喜欢
    • 1970-01-01
    • 2021-10-13
    • 2020-11-09
    • 2016-03-09
    • 2021-08-19
    • 2020-10-26
    • 2021-01-25
    • 2020-10-30
    相关资源
    最近更新 更多