使用firebase-functions-test测试Cloud Firestore函数时遇初始化错误
我之前也碰到过一模一样的问题,本质是测试环境和生产环境的Firebase App初始化是完全独立的——哪怕你的函数代码里已经写了initializeApp(),测试SDK还是需要在测试代码里单独做配置初始化,不然测试运行时根本找不到对应的App实例。
给你几个具体的解决步骤,亲测有效:
先正确初始化测试SDK
测试文件开头一定要先导入firebase-functions-test,并传入你的项目基础配置(本地测试可以简化,但项目ID最好填上)。比如:// test.js 开头代码 const test = require('firebase-functions-test')({ projectId: '你的项目ID', // 替换成你Firebase控制台里的真实项目ID }); // 初始化测试SDK之后,再导入你的函数文件 const myFunctions = require('../index');如果你需要用到真实Firebase资源或者权限控制,可以在第二个参数传入服务账号密钥路径,但本地用仿真器测试的话完全可以省略这个参数。
确保函数代码里的App初始化全局执行
检查你的函数入口文件(比如index.js),确认admin.initializeApp()是在所有函数定义之前全局执行的,别嵌套在某个函数里。比如:// index.js const admin = require('firebase-admin'); admin.initializeApp(); // 必须放在所有函数定义之前,全局执行 // 然后定义你的updateActiveNotesCount函数 exports.updateActiveNotesCount = functions.firestore.document('...').onWrite(...);用测试SDK的工具生成模拟对象
复制示例代码的时候,别自己手动造Firestore的快照或上下文对象,一定要用测试SDK提供的makeDocumentSnapshot这类工具,这样生成的对象会自动关联测试环境的Firebase App。比如你的测试用例可以这么写:describe('updateActiveNotesCount', () => { // 每个测试套件结束后清理资源,避免App残留导致冲突 after(() => { test.cleanup(); }); it('应该在添加活跃笔记时更新计数', async () => { // 生成模拟的文档快照 const mockSnap = test.firestore.makeDocumentSnapshot( { active: true }, 'notes/test-note-id' ); // 生成模拟的上下文参数 const mockContext = { params: { userId: 'test-user-id' } }; // 调用你的函数 await myFunctions.updateActiveNotesCount(mockSnap, mockContext); // 这里添加你的断言逻辑,比如验证用户文档里的count字段是否正确更新 }); });别忘了配置测试环境变量(如果用仿真器)
如果你是用Firestore仿真器做本地测试,要在测试脚本里加上环境变量,确保测试代码指向仿真器。比如package.json里的测试脚本可以改成:"scripts": { "test": "FIRESTORE_EMULATOR_HOST=localhost:8080 jest" }
核心思路就是:测试环境需要单独初始化测试SDK,用SDK自带的工具生成模拟数据,测试结束后清理资源——这样就能彻底解决找不到默认App的问题了。
内容的提问来源于stack exchange,提问作者Brandon

