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

Jest测试Firestore报错:ReferenceError: 无法在初始化前访问'mockFirestore'

问题原因

Jest会将jest.mock调用自动提升到模块所有代码的最顶部执行,这意味着当你的jest.mock工厂函数执行时,后面定义的mockFirestore变量还未完成初始化,因此抛出了"Cannot access 'mockFirestore' before initialization"的错误。

修复方案

将所有mock函数的定义移到jest.mock的工厂函数内部,或者通过链式调用避免提前引用未初始化的变量。以下是两种可行的修复代码:

方案一:在mock工厂函数内定义所有mock变量

import { RoleService } from "../../services/RoleService";
import { CustomError } from "../../exceptions/custom_error";

// 提前声明变量,方便测试中修改mock行为
let mockGet: jest.Mock;
let mockDoc: jest.Mock;
let mockCollection: jest.Mock;
let mockFirestore: jest.Mock;

jest.mock("firebase-admin", () => {
  // 在工厂函数内部初始化所有mock函数
  mockGet = jest.fn();
  mockDoc = jest.fn().mockReturnValue({ get: mockGet });
  mockCollection = jest.fn().mockReturnValue({ doc: mockDoc });
  mockFirestore = jest.fn().mockReturnValue({ collection: mockCollection });

  return {
    firestore: jest.fn().mockReturnValue(mockFirestore()),
  };
});

describe("RoleService Unit Tests", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  test("should throw error when role does not exist", async () => {
    const roleId = "role123";

    mockGet.mockResolvedValue({
      exists: false,
      data: jest.fn().mockReturnValue(null),
      id: roleId,
    });

    await expect(RoleService.getRoleById(roleId)).rejects.toThrow(CustomError.roleNotFound());
  });
});

方案二:链式调用mock函数,无需额外变量声明

import { RoleService } from "../../services/RoleService";
import { CustomError } from "../../exceptions/custom_error";
import admin from "firebase-admin";

jest.mock("firebase-admin", () => {
  return {
    firestore: jest.fn().mockReturnValue({
      collection: jest.fn().mockReturnValue({
        doc: jest.fn().mockReturnValue({
          get: jest.fn()
        })
      })
    })
  };
});

describe("RoleService Unit Tests", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  test("should throw error when role does not exist", async () => {
    const roleId = "role123";
    // 从mock实例中获取get函数并修改其返回值
    const mockGet = (admin.firestore() as any).collection().doc().get;
    mockGet.mockResolvedValue({
      exists: false,
      data: jest.fn().mockReturnValue(null),
      id: roleId,
    });

    await expect(RoleService.getRoleById(roleId)).rejects.toThrow(CustomError.roleNotFound());
  });
});
原理说明

两种方案都是通过将mock函数的定义逻辑放到jest.mock的工厂函数内部,确保当Jest提升执行jest.mock时,所有依赖的mock函数已经完成初始化,从根源上解决了变量提前访问的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:52:27