TypeScript函数式编程中单元测试依赖自动Mock工具函数实现
实现自动Mock函数依赖的createDeps工具函数
完整实现代码
import type { Mock } from 'jest'; // 从目标函数中提取其第一个参数(依赖对象)的类型 type ExtractDeps<Fn> = Fn extends (deps: infer D, ...args: any[]) => any ? D : never; // 定义所有属性均为jest.Mock的依赖类型 type MockedDeps<D> = { [K in keyof D]: Mock; }; export function createDeps<Fn extends (deps: any, ...args: any[]) => any>( customMocks?: Partial<MockedDeps<ExtractDeps<Fn>>> ): MockedDeps<ExtractDeps<Fn>> { const deps = {} as MockedDeps<ExtractDeps<Fn>>; const depKeys = Object.keys({} as ExtractDeps<Fn>) as Array<keyof ExtractDeps<Fn>>; depKeys.forEach(key => { deps[key] = customMocks?.[key] ?? jest.fn(); }); return deps; }
使用示例
假设你有如下函数和依赖类型:
type BreakfastDeps = { scrambleEggs: () => Promise<string>; makeToast: () => string; personMakingTheToast: (name: string) => void; }; async function createBreakfast(deps: BreakfastDeps) { await deps.scrambleEggs(); const toast = deps.makeToast(); deps.personMakingTheToast('Alice'); return `Breakfast ready: ${toast}`; }
在单元测试中使用createDeps:
test('createBreakfast 正常工作', async () => { // 仅自定义需要特殊配置的mock const makeToast = jest.fn().mockReturnValueOnce("It's ready"); // 自动生成所有依赖,自定义mock会覆盖默认值 const deps = createDeps<typeof createBreakfast>({ makeToast }); const result = await createBreakfast(deps); expect(result).toBe("Breakfast ready: It's ready"); expect(deps.scrambleEggs).toHaveBeenCalled(); expect(deps.personMakingTheToast).toHaveBeenCalledWith('Alice'); });
核心特性说明
- 类型自动推导:通过
ExtractDeps泛型自动提取目标函数的依赖类型,无需手动重复声明依赖结构。 - 按需自定义Mock:仅需传入需要特殊配置(如返回值、实现逻辑)的mock,其余依赖自动生成默认的
jest.fn()。 - 类型安全:
MockedDeps确保所有依赖属性都是jest.Mock类型,避免类型不匹配问题。 - 通用性:适用于任何接收依赖对象作为第一个参数的函数,无需针对不同函数修改工具代码。
内容的提问来源于stack exchange,提问作者Prasanth Louis
相关产品推荐
相关产品推荐

