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

使用ts-jest/utils mock数据库调用时db函数返回undefined如何解决

问题原因
  • 未给mock的getDbConnection设置返回值:jest.mock("../src/utils/db")默认只会生成空mock函数作为默认导出,调用该函数的返回值为undefined。控制器代码在模块顶层就执行了const db = getDbConnection()初始化数据库实例,此时拿到的db就是undefined,后续调用db.query自然无法返回预期结果。
  • mocked()方法用法错误:ts-jest提供的mocked工具仅用于TypeScript类型断言,作用是将普通对象转换为带Jest Mock类型提示的对象,不会为mock函数添加任何实际实现,仅写mocked(db)没有任何实际作用。
  • 未mockquery方法的返回值:就算正确返回了db实例,未设置返回值的mockquery方法默认返回undefined,且不会返回异步Promise,会导致控制器逻辑异常。
修复方案

需要给Jest Mock补全完整实现,同时注意模块导入顺序,确保mock逻辑在控制器导入之前执行(因为控制器在顶层就初始化了db实例)。修改后的测试代码参考如下:

import { expect, describe, it, jest, afterAll } from "@jest/globals";
import { mocked } from "ts-jest/utils";
import request from "supertest";

// 提前定义mock的query方法,方便后续调整返回值
const mockQuery = jest.fn();
// 先执行mock逻辑,覆盖db模块的导出
jest.mock("../src/utils/db", () => ({
  default: jest.fn(() => ({
    query: mockQuery
  }))
}));

// 所有依赖db模块的导入都要放在jest.mock之后,避免拿到未mock的原方法
import db from "../src/utils/db";
import app from "../src/app"; // 替换为你的Express应用实例的实际路径

const mockedGetDbConnection = mocked(db);

describe("Test Controller", () => {
  afterAll(() => {
    jest.resetAllMocks();
  });

  it("should retrieve all", async () => {
    // 给本次测试的query方法设置模拟返回数据
    const mockReturnData = { data: ["data"] };
    mockQuery.mockResolvedValueOnce(mockReturnData);

    await request(app)
      .get("/data")
      .expect(200)
      .expect((res) => {
        expect(res.body.data).toContain("data");
        // 可额外添加断言验证query方法被正常调用
        expect(mockQuery).toHaveBeenCalled();
      });
  });
});

可选优化

如果不想受模块导入顺序的限制,可以调整控制器逻辑,将const db = getDbConnection()的初始化逻辑放到请求处理函数内部,或者封装为懒加载形式,测试时可以随时调整mock返回值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 08:30:03