You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单元测试中向Firebase Functions模拟器传递context参数

解决Firebase onCall云函数单元测试传递context参数的问题

根因说明

你使用的是Firebase onCall 类型HTTPS云函数,这类函数有官方统一的请求协议,不允许在请求Body中手动传入context字段:context参数是云函数运行时自动从请求头、认证信息等内容解析生成的,不是客户端通过Body传递的字段,因此你直接在Body中添加context字段会触发非法字段校验错误。

解决方法

方案1:保留chai-http调用方式的调整

将认证信息放到请求头中,Body仅保留业务数据字段即可:

  1. 请求Body中删除context相关内容,仅保留data字段
  2. 本地模拟器测试可以直接使用模拟器专属请求头X-Firebase-Auth-Emulator-Uid指定用户UID,不需要生成真实的认证Token,云函数会自动解析该头生成对应的context.auth内容
    修改后测试代码示例:
it("function_call", async() => {
    await new Promise((resolve, reject) => {
        chai.request(url)
            .post("")
            // 配置必要请求头
            .set("Content-Type", "application/json")
            // 模拟器专属头,直接指定要模拟的用户UID
            .set("X-Firebase-Auth-Emulator-Uid", USER_ID)
            // Body仅保留业务数据
            .send({
                data: {
                    id: FILE_ID
                }
            })
            .end(function(err, res) {
                console.info(JSON.stringify(res));
                const payload = JSON.parse(res.text);
                chai.expect(payload.error).not.null;
                resolve();
            });
    });
    // 后续断言逻辑不变
    const afterCall = await firestore.collection(`users/${USER_ID}/files/${FILE_ID}`).get();
    chai.expect(afterCall.empty).is.true;
});

如果需要传入完整的自定义Token,将上面的X-Firebase-Auth-Emulator-Uid头替换为Authorization: Bearer ${USER_TOKEN}即可。

方案2:官方推荐单元测试方案(更简洁,无需发HTTP请求)

使用Firebase官方提供的firebase-functions-test工具包,可以直接调用云函数业务逻辑,手动传入自定义context,不需要走HTTP请求,更适配单元测试场景:

  1. 首先安装依赖
npm install firebase-functions-test --save-dev
  1. 调整后的测试代码示例
// 初始化测试工具,填入你的测试项目ID
const test = require('firebase-functions-test')({
  projectId: 'dev-export',
});
// 导入你的云函数逻辑
const myFunctions = require('./index.js');

it("function_call", async() => {
    // 自由构造你需要的context参数
    const mockContext = {
        auth: {
            uid: USER_ID,
            token: USER_TOKEN
        }
    };
    // 直接调用业务逻辑,不需要发起HTTP请求
    await myFunctions.doSomething({id: FILE_ID}, mockContext);
    // 后续断言逻辑不变
    const afterCall = await firestore.collection(`users/${USER_ID}/files/${FILE_ID}`).get();
    chai.expect(afterCall.empty).is.true;
});

内容的提问来源于stack exchange,提问作者koma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 02:06:09