柯里化函数用于单元测试中预设mock返回数据,支持分步传参、可复用、带状态的模拟行为,可封装条件返回、参数匹配及与jest mock结合使用,并需在beforeeach中重置状态防污染。

在单元测试中,用柯里化函数预设 Mock 返回数据,核心是让 Mock 函数支持“分步传参 + 预设响应”,从而灵活适配不同调用场景。它不直接替代 jest.fn().mockReturnValue(),而是帮你封装出可复用、带状态的模拟行为。
用柯里化构造可配置的 Mock 工厂
把 Mock 创建逻辑柯里化,第一层接收预期返回值,第二层返回实际被调用的函数。这样既能复用,又能按需定制每个测试用例的响应:
const createMockApi = (response) => () => Promise.resolve(response);
// 使用示例
const mockFetchUser = createMockApi({ id: 1, name: 'Alice' });
const mockFetchPosts = createMockApi([{ id: 1, title: 'Hello' }]);
// 在 test 中注入
jest.mock('../api', () => ({
fetchUser: mockFetchUser,
fetchPosts: mockFetchPosts,
}));
支持参数匹配与条件返回(带记忆的柯里化)
当需要根据入参返回不同结果时,可让柯里化函数内部维护映射表或判断逻辑:
const createConditionalMock = (map) => (input) => {
if (map.has && map.has(input)) return Promise.resolve(map.get(input));
if (typeof map === 'function') return Promise.resolve(map(input));
return Promise.resolve(map);
};
// 按 ID 返回不同用户
const mockFetchUser = createConditionalMock(
new Map([
[1, { id: 1, name: 'Alice' }],
[2, { id: 2, name: 'Bob' }],
])
);
// 或用函数动态生成
const mockGenerateToken = createConditionalMock((userId) =>
`token-${userId}-${Date.now()}`
);
与 Jest Mock 结合:替换模块方法并预设行为
在 jest.mock 或 jest.doMock 中使用柯里化函数,确保每次 require 都拿到已预设好响应的版本:
// __mocks__/axios.js
import axios from 'axios';
// 柯里化一个可延迟/报错/成功控制的 mock
const createAxiosMock = (config) => {
return {
get: jest.fn().mockImplementation((url) => {
if (config.throw) throw new Error(config.message || 'Network error');
return Promise.resolve({ data: config.data || {} });
}),
};
};
// 导出默认预设(如成功响应)
export default createAxiosMock({ data: { ok: true } });
测试文件中可覆盖:
jest.mock('axios', () =>
require('./__mocks__/axios').default({ data: { id: 123 } })
);
避免副作用:每次测试重置柯里化 Mock 状态
柯里化函数若闭包内含可变状态(如计数器、缓存),需在 beforeEach 清理,否则测试间污染:
- 用
jest.clearAllMocks()重置jest.fn()实例 - 若柯里化函数自身有内部状态(如记录调用次数),把它设计成工厂函数,每次测试新建实例
- 避免在模块顶层定义带状态的柯里化 Mock,改在
test或beforeEach内创建
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











