使用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)没有任何实际作用。- 未mock
query方法的返回值:就算正确返回了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
相关产品推荐
相关产品推荐

