使用Vitest测试Firebase安全规则时,如何获取FirebaseError的堆栈跟踪?
问题描述
我正在使用Vitest和Firebase测试包@firebase/rules-unit-testing为Web应用搭建安全测试,整体流程可行,但遇到一个问题:FirebaseError的输出仅能告知违反了哪条Firestore安全规则,却无法显示测试代码中对应的出错行。
当前错误输出如下:
FAIL tests/security.test.ts > inviting someone to an ancestor board with nested sharing FirebaseError: 7 PERMISSION_DENIED: evaluation error at L44:24 for 'create' @ L44, evaluation error at L45:32 for 'update' @ L45, false for 'create' @ L44 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { code: 'permission-denied', customData: undefined } ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯ Test Files 1 failed (1) Tests 6 failed (6) Start at 13:24:40 Duration 520ms
我希望错误输出能像普通抛出错误那样,显示测试文件的行号及代码位置,示例如下:
FAIL tests/security.test.ts > inviting someone to an ancestor board with nested sharing Error: oh no ❯ tests/security.test.ts:239:9 237| 238| test("inviting someone to an ancestor board with nested sharing", async () => { 239| throw new Error("oh no"); | ^
请问如何让FirebaseError的输出中包含这样的堆栈跟踪?
解决方法
以下几种方法可以实现需求:
手动捕获并重新抛出错误
在测试代码中用try/catch包裹Firestore操作,捕获FirebaseError后,将其作为新Error的原因抛出,触发Vitest生成包含当前测试行号的堆栈:test("inviting someone to an ancestor board with nested sharing", async () => { try { // 你的Firestore操作代码,比如create/update await db.collection("boards").add(...); } catch (err) { if (err instanceof FirebaseError) { throw new Error(err.message, { cause: err }); } throw err; } });调整Vitest配置
在vitest.config.ts中修改错误相关配置,确保Vitest完整显示错误堆栈:export default defineConfig({ test: { stackTrace: true, serializeErrors: false, // 关闭错误序列化,保留原始错误信息 }, });自定义断言包装器
封装通用的权限验证断言函数,自动处理错误抛出逻辑,减少重复代码:async function assertAllowed(operation: () => Promise<void>) { try { await operation(); } catch (err) { if (err instanceof FirebaseError) { throw new Error(`权限验证失败:${err.message}`, { cause: err }); } throw err; } } // 使用示例 test("inviting someone to an ancestor board with nested sharing", async () => { await assertAllowed(async () => { await db.collection("boards").add(...); }); });启用Firebase测试详细日志
虽然不会直接显示测试行号,但可以结合堆栈跟踪辅助排查问题:import { setLogLevel } from "@firebase/rules-unit-testing"; // 在测试初始化阶段设置 setLogLevel("debug");
内容的提问来源于stack exchange,提问作者Evan Summers
相关产品推荐
相关产品推荐

