Firebase离线单元测试使用firebase-emulator时报无法加载默认凭据错误
问题根因
你调用admin.firestore().get()时,Admin SDK默认尝试连接线上Firebase服务,未检测到凭证就抛出该错误,你的代码有两处核心问题:
admin.initializeApp()执行时机早于sinon.stub,stub完全没有生效,真实的初始化逻辑走了线上服务的校验逻辑- 没有将Admin SDK指向本地Firestore模拟器,也没有配置测试用的环境变量跳过凭证校验
修复步骤
- 首先在测试脚本启动前配置三个环境变量,不需要真实项目信息
# macOS/Linux环境 export GCLOUD_PROJECT=test-project-id export FIRESTORE_EMULATOR_HOST=localhost:8080 export FIREBASE_FUNCTIONS_EMULATOR_HOST=localhost:5001
Windows环境用set命令配置,或者直接在测试代码最顶部添加:
process.env.GCLOUD_PROJECT = "test-project-id"; process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
- 调整before块的初始化逻辑,移除无效的stub顺序,如果你的业务代码里也有
initializeApp调用,保留stub即可,注意调整执行顺序 - 调用
wrapped方法时加await,确保云函数逻辑执行完成后再读取数据库校验结果
修改后的核心代码示例
describe('Cloud Functions', function() { let myFunctions: any, adminInitStub: sinon.SinonStub<[options?: admin.AppOptions, name?: string], admin.app.App>; // 初始化firebase-functions-test时指定测试项目id const tester = funcTest({ projectId: "test-project-id" }); before(async () => { // 先stub再执行任何initializeApp调用 adminInitStub = sinon.stub(admin, "initializeApp").returns(admin.app()); // 不需要额外传参,设置了环境变量后会自动连接模拟器,无需凭证 admin.initializeApp(); myFunctions = await import("../src/index") }); after(() => { adminInitStub.restore(); tester.cleanup(); }); describe("dbOrderServiceOnCreated", () => { it("should add snapshot successfully", async function() { const wrapped = tester.wrap(myFunctions.dbOrderServiceOnCreated) // 加await等待云函数执行完成 await wrapped(serviceOrderSnap) this.timeout(0); const value = await admin.firestore().collection(constants.collectionOrdersService).get(); return chai.assert.equal(value.size, 1); }) }) })
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

