如何在Jest+TypeScript中实现Postgres Pool的可定制Mock
解决方案
要在不同测试用例中定制Postgres Pool的query方法返回值,核心是将mock的query函数暴露出来,让每个测试都能独立配置。以下是具体实现步骤:
1. 重构Mock逻辑
直接导入pg模块并mock,用jest.mocked获取类型安全的mock对象,避免闭包导致无法访问内部mock函数:
import { describe, expect, test, jest, beforeEach } from "@jest/globals"; import { checkLimits } from "./db"; import { MINUTES } from "./constants"; import { Pool } from "pg"; // Mock整个pg模块 jest.mock("pg"); // 获取类型安全的Pool构造函数mock const MockPool = jest.mocked(Pool); // 声明全局可用的mock query函数 let mockQuery: jest.Mock;
2. 初始化测试前置条件
在beforeEach中重置所有mock,确保每个测试用例的mock状态独立:
beforeEach(() => { // 重置Pool构造函数的mock记录 MockPool.mockClear(); // 创建新的mock query函数 mockQuery = jest.fn(); // 让Pool构造函数返回带有mock query的实例 MockPool.mockReturnValue({ query: mockQuery, } as unknown as InstanceType<typeof Pool>); });
3. 在测试用例中定制返回值
现在可以直接在每个测试里用mockQuery.mockReturnValueOnce设置专属返回值:
describe("checkLimits", () => { test("allows reasonable usage by address", async () => { mockQuery.mockReturnValueOnce({ rows: [ { timestamps: [Date.now() - 10 * MINUTES], }, ], }); await checkLimits("abcdef"); // 可选:添加断言验证query调用情况 expect(mockQuery).toHaveBeenCalled(); }); test("also allows more usage", async () => { mockQuery.mockReturnValueOnce({ rows: [ { timestamps: [ Date.now() - 10 * MINUTES, Date.now() - 3 * MINUTES, Date.now() - 2 * MINUTES, ], }, ], }); await checkLimits("abcdef"); expect(mockQuery).toHaveBeenCalled(); }); });
关键说明
- 避免了闭包封装mock导致的外部无法访问问题,直接将
mockQuery暴露为全局变量。 beforeEach确保每个测试用例的mock都是全新的,不会出现测试间的状态污染。jest.mocked解决了TypeScript的类型校验问题,无需额外复杂的类型断言。
内容的提问来源于stack exchange,提问作者mikemaccana
相关产品推荐
相关产品推荐

