React Jest测试时expect(jest.fn()).toHaveBeenCalledWith调用次数为0如何解决?
问题根因
你遇到的两个报错存在直接关联:先触发的TypeError: Cannot read property 'push' of undefined导致history.push逻辑根本无法执行,自然会出现调用次数为0的断言失败。具体问题和修复方案如下:
1. 修复push is undefined报错
该问题是由jest.mock的变量提升机制导致的:
jest.mock会被Jest自动提升到文件最顶部执行,此时你在外部声明的mockHistoryPush还未初始化,所以useHistory返回的对象里push是undefined。
修复后的mock写法:
// 把mock方法定义放到jest.mock内部,避免变量提升导致的未定义 jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useHistory: () => ({ push: jest.fn(), }), }));
测试用例内获取mock实例:
it('should render card with data when clicked for *', async () => { // 从mock的react-router-dom中获取push的mock实例 const mockHistoryPush = require('react-router-dom').useHistory().push; SearchWrapper = mount(<CustomerSearch />); // 后续逻辑 })
2. 修复调用次数为0的问题
解决完push的定义问题后,如果还是断言失败,按以下步骤排查:
- 先确认你已经给表单输入框赋值为
*:测试用例中直接点击提交按钮不会自动填充表单值,需要先模拟输入操作,示例:// 替换成你实际的输入框选择器 SearchWrapper.find('input#searchInput').simulate('change', { target: { value: '*' } }); - 确认你已经mock了提交触发的API请求:需要让接口返回
searchResult.data长度大于1的结果,否则不会走到跳转分支。可以在测试前先打桩接口返回值。 - 增加异步等待逻辑,确保所有异步任务执行完成后再断言,推荐用
waitFor包裹断言:import { waitFor } from '@testing-library/react'; // 替换原有断言 await waitFor(() => { expect(mockHistoryPush).toHaveBeenCalledWith(locationStateMock2); }) - 可以通过校验
console.log('length greater than 1')是否在测试运行时输出,确认逻辑是否走到了跳转分支。
内容的提问来源于stack exchange,提问作者pavan sai
相关产品推荐
相关产品推荐

