Jest+TypeScript测试双Axios调用控制器遇axios.default函数错误
解决Jest+TypeScript下Axios两种调用方式的Mock问题
问题原因
你遇到的TypeError: (0 , axios_1.default) is not a function错误,是因为当前仅Mock了axios.post方法,但未正确Mock Axios的默认导出函数(也就是直接调用axios()的情况)。TypeScript编译后会尝试访问Axios模块的default属性,而你的Mock没有提供这个属性,导致调用失败。
解决方案
下面提供两种可靠的Mock方式,确保同时覆盖axios.post和直接调用axios()的场景:
方式一:使用jest.mock工厂函数Mock整个Axios模块
直接在测试文件顶部Mock Axios,同时定义默认导出函数和post方法的Mock:
// 全局Mock Axios模块 jest.mock('axios', () => { // 创建Mock函数作为Axios默认导出(对应直接调用axios()的场景) const mockAxiosInstance = jest.fn(); // 给Mock实例添加post方法的Mock mockAxiosInstance.post = jest.fn(); // 返回符合Axios导出结构的对象 return { default: mockAxiosInstance, // 若代码中存在`import { post } from 'axios'`的写法,需额外导出post post: mockAxiosInstance.post, }; }); // 导入依赖和待测试函数 import axios from 'axios'; import eventController from './path-to-your-eventController'; describe('eventController', () => { // 每个测试用例前重置Mock调用记录 beforeEach(() => { jest.clearAllMocks(); }); test('正确调用两种Axios请求方式', async () => { // 给两个Mock方法设置返回值 (axios as jest.Mock).mockResolvedValue({ data: 'API2 模拟响应' }); axios.post.mockResolvedValue({ data: 'API1 模拟响应' }); // 执行待测试函数 await eventController(); // 验证axios.post的调用参数 expect(axios.post).toHaveBeenCalledWith( expect.stringContaining('/API1'), { data: 'data for API1' } ); // 验证直接调用axios()的参数 expect(axios).toHaveBeenCalledWith({ method: 'POST', url: expect.stringContaining('/API2'), data: { data: 'data for API2' } }); }); });
方式二:手动创建Mock模块(适合复杂场景)
在项目根目录创建__mocks__/axios.ts文件,统一管理Axios的Mock逻辑:
// __mocks__/axios.ts const mockAxios = jest.fn(); mockAxios.post = jest.fn(); export default mockAxios; export const post = mockAxios.post;
然后在测试文件中直接使用jest.mock('axios')即可自动加载这个Mock模块,后续测试逻辑和方式一一致。
额外注意事项
- 避免babel-jest和ts-jest冲突:你的依赖中同时安装了
babel-jest和ts-jest,但ts-jest已经内置了TypeScript编译和babel处理能力,建议移除babel-jest,并确保jest.config.js中仅使用ts-jest预设:
// jest.config.js module.exports = { preset: 'ts-jest', testEnvironment: 'node', transform: { '^.+\\.tsx?$': 'ts-jest', }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], };
- 类型断言:在测试中使用
(axios as jest.Mock)是因为TypeScript不知道我们已经将Axios替换为Mock函数,需要手动断言类型以调用Mock相关方法。
内容的提问来源于stack exchange,提问作者Gab Agoncillo
相关产品推荐
相关产品推荐

