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

如何在Jest测试中正确Mock TypeORM的QueryRunner.manager.findOne

问题

我正在测试一个接收QueryRunner作为参数、并执行queryRunner.manager.findOne的函数,核心代码如下:

const logistic = await queryRunner.manager.findOne(Logistic, {
  where: {
    id: logisticsId || scooterLogisticId,
  },
});

在Jest测试中,我已经Mock了data-source和database模块:
data-source模块原代码:

const dataSource = addTransactionalDataSource({
  dataSource: new DataSource(ormConfig),
  patch: true,
});

database模块原代码:

export const database = new DatabaseManager();

我的测试文件代码如下:

import { dataSource } from "../../../../data-source";

jest.mock("../../../../data-source");
jest.mock("../../../../helpers/database")
describe("isScooter", () => {
  // Shared mock data
  const mockEmail = "test@example.com";
  const mockParsedBody = {
    completedAt: new Date(),
    slotIdInbound: "DEF456",
    fees: [{ value: 10 }, { value: 20 }],
    inspectionNote: "Some inspection notes",
    agent: "John Doe",
    location: "San Francisco",
    productType: "scooter",
  };

  let queryRunner: QueryRunner;

  beforeEach(async () => {
    queryRunner = dataSource.createQueryRunner();
  });

  afterEach(async () => {
    jest.clearAllMocks()
  })

  // ... 其他测试代码
  (queryRunner.manager.findOne as jest.Mock).mockResolvedValueOnce(mockLogistic3);
});

但执行到(queryRunner.manager.findOne as jest.Mock).mockResolvedValueOnce(mockLogistic3);时,出现queryRunner未定义的错误,请问如何正确Mock并实例化QueryRunner?

解决方案

问题根源是你没有正确MockdataSource.createQueryRunner()的返回值,导致queryRunner实际为undefined。以下是正确的Mock步骤:

  • 提前定义完整的Mock结构
    先创建Mock的findOne方法、manager对象和QueryRunner实例,确保每个核心方法都是Jest Mock函数。

  • 指定createQueryRunner的返回值
    在beforeEach中,明确让dataSource.createQueryRunner返回我们预定义的Mock QueryRunner对象。

修改后的测试代码示例:

import { dataSource } from "../../../../data-source";
import { QueryRunner } from "typeorm";

jest.mock("../../../../data-source");
jest.mock("../../../../helpers/database")

// 预定义Mock组件
const mockFindOne = jest.fn();
const mockManager = { findOne: mockFindOne };
const mockQueryRunner = { manager: mockManager } as unknown as QueryRunner;

describe("isScooter", () => {
  // Shared mock data
  const mockEmail = "test@example.com";
  const mockParsedBody = {
    completedAt: new Date(),
    slotIdInbound: "DEF456",
    fees: [{ value: 10 }, { value: 20 }],
    inspectionNote: "Some inspection notes",
    agent: "John Doe",
    location: "San Francisco",
    productType: "scooter",
  };

  let queryRunner: QueryRunner;

  beforeEach(async () => {
    // 绑定createQueryRunner的返回值
    (dataSource.createQueryRunner as jest.Mock).mockReturnValue(mockQueryRunner);
    queryRunner = dataSource.createQueryRunner();
    // 重置findOne的Mock状态,避免测试间污染
    mockFindOne.mockReset();
  });

  afterEach(async () => {
    jest.clearAllMocks()
  })

  test("your test case", async () => {
    // 设置findOne的返回值
    mockFindOne.mockResolvedValueOnce(mockLogistic3);
    
    // 执行待测试函数并传入queryRunner
    const result = await yourTestFunction(queryRunner);
    
    // 断言findOne的调用逻辑
    expect(mockFindOne).toHaveBeenCalledWith(Logistic, {
      where: { id: expect.any(String) }
    });
    // 其他业务逻辑断言
  });
});
  • 关键注意事项
    1. 必须确保dataSource.createQueryRunner的Mock返回值是结构完整的对象,而非默认的undefined
    2. 单独维护mockFindOne函数,便于在不同测试用例中灵活设置返回值和校验调用情况
    3. 在beforeEach中重置Mock状态,避免测试用例之间的状态污染

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:10:22