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

如何用Jest模拟Firestore v9的getDocs()方法?

解决Firebase v9 + Jest模拟getDocs的问题

问题根源

  1. 第一个错误Cannot read properties of undefined (reading 'docs'):你模拟的getDocs返回的docs是单个对象,但原代码中调用了forEach,要求docs必须是数组。
  2. 第二个错误_firestore.getDocs.mockImplementation is not a function:你没有通过Jest正确mock整个firebase/firestore模块,直接修改getDocs本身不会让它变成Jest mock函数,自然没有mockImplementation方法。

正确的模拟步骤

1. 先Mock整个Firebase Firestore模块

在测试文件最顶部,用jest.mock将firebase/firestore的核心方法转为Jest mock函数:

import { getFirestore, collection, query, where, getDocs } from 'firebase/firestore';

// Mock整个firestore模块
jest.mock('firebase/firestore', () => ({
  getFirestore: jest.fn(),
  collection: jest.fn(),
  query: jest.fn(),
  where: jest.fn(),
  getDocs: jest.fn()
}));

2. 在测试用例中配置Mock返回值

在具体测试用例里,根据业务逻辑设置各个mock函数的返回值:

test('你的测试用例名称', async () => {
  // 1. 模拟getFirestore返回假的实例
  const mockFirestoreInstance = {};
  (getFirestore as jest.Mock).mockReturnValue(mockFirestoreInstance);

  // 2. 模拟collection返回假的集合引用
  const mockCollectionRef = {};
  (collection as jest.Mock).mockReturnValue(mockCollectionRef);

  // 3. 模拟query返回假的查询对象(where返回任意值即可,仅用于构建查询条件)
  const mockQuery = {};
  (query as jest.Mock).mockReturnValue(mockQuery);
  (where as jest.Mock).mockReturnValue({});

  // 4. 关键:模拟getDocs返回符合要求的结构
  // docs必须是数组,每个元素要有data()方法返回测试数据
  (getDocs as jest.Mock).mockResolvedValue({
    docs: [
      {
        data: () => ({ id: 'test-id-1', name: '测试名称1' })
      },
      {
        data: () => ({ id: 'test-id-2', name: '测试名称2' })
      }
    ]
  });

  // 5. 执行你要测试的函数
  await yourFunctionToTest();

  // 6. 可选:添加断言验证mock函数调用情况
  expect(getDocs).toHaveBeenCalledWith(mockQuery);
});

3. 修复原代码的潜在问题

原代码中dataDict[data['id']].name = data.name存在风险:如果dataDict中没有data['id']对应的键,会抛出Cannot set properties of undefined错误,建议提前初始化:

const dataDict: { [key: string]: {id: string, name: string} } = {};
(await getDocs(dataList)).docs.forEach((dataItem) => {
  const data = dataItem.data();
  // 先初始化键对应的对象,避免报错
  if (!dataDict[data.id]) {
    dataDict[data.id] = { id: data.id, name: '' };
  }
  dataDict[data.id].name = data.name;
});

为什么之前的模拟失败?

  • 你直接修改getDocs的mockImplementation,但此时getDocs还不是Jest mock函数,必须先通过jest.mock将其转为mock函数后,才能使用mockImplementation或mockResolvedValue。
  • 你模拟的docs是单个对象,而原代码需要它是数组才能调用forEach,这是第一个错误的直接原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:30:41