React组件测试时为什么mock的API没有被调用?

司徒惠泽 阅读 59

我在用Jest+React Testing Library测试一个组件时遇到了问题。组件里用useEffect调用了外部API,我按教程写了mock但测试总是失败:


// userApi.js
export const fetchUser = jest.fn(() => Promise.resolve({ name: 'mock' }));

// UserComponent.test.js
import { render, screen } from '@testing-library/react';
import { fetchUser } from './userApi';
import UserComponent from './UserComponent';

test('should call API on mount', async () => {
  fetchUser.mockClear();
  render();
  expect(fetchUser).toHaveBeenCalledTimes(1); // 这里始终显示0
});

我已经确认组件确实在useEffect里调用了fetchUser,但测试时mock的函数计数一直是0。试过在测试前加jest.mock(‘./userApi’)也不行,控制台没有报错但就是没触发。是不是mock的写法有问题?

我来解答 赞 8 收藏
二维码
手机扫码查看
1 条解答
FSD-玉茂
问题出在你没有正确地对 userApi 进行 mock。即使你写了 jest.fn(),但如果模块加载时没有被正确替换掉,组件还是会调用原始的实现。我之前也碰到过这个问题。

解决方法很简单:你需要在测试文件中明确地 mock 整个 userApi.js 模块。像这样:

import { render } from '@testing-library/react';
import UserComponent from './UserComponent';
jest.mock('./userApi'); // 这里mock整个模块

// 确保重新从mock后的模块中引入fetchUser
import { fetchUser } from './userApi';

test('should call API on mount', async () => {
fetchUser.mockClear();
render(<UserComponent />); // 别忘了传入组件!
expect(fetchUser).toHaveBeenCalledTimes(1);
});


重点是:
1. jest.mock('./userApi') 必须加在测试文件顶部,确保模块被正确替换。
2. 重新导入 fetchUser,保证你操作的是 mock 后的对象。
3. 在 render() 时别忘了传入你的组件实例。

试试这个修改,应该就能正常工作了!如果还是有问题,可能是其他地方有干扰,比如组件内部的逻辑。
点赞 7
2026-01-30 11:04