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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:04:55