Jest + Enzyme测试中Mock函数未被调用问题求助
解决submitChoice() Mock函数点击断言失败的问题
我看到你在测试React组件时,尝试Mock负责API调用的submitChoice()函数,期望点击#buttonOption1按钮时触发它,但测试断言失败,提示Expected mock function to have been called.。结合你给出的测试代码片段,我整理了几个常见的问题点和对应的解决方案:
1. 检查Mock的方式是否匹配函数的实际定义
首先要明确submitChoice是组件的实例方法、props传入的函数,还是从外部模块导入的函数,不同的定义方式Mock的方法也不一样:
情况1:submitChoice是组件的实例方法(类组件)
如果submitChoice是类组件的实例方法,你需要Mock组件原型上的方法,而不是随便创建一个Mock函数。比如:
import React from 'react'; import App from './App'; import { mount } from 'enzyme'; describe('App', () => { it('should call the submitChoice method on click', async () => { // 1. Mock组件原型上的submitChoice方法 const mockSubmit = jest.spyOn(App.prototype, 'submitChoice').mockResolvedValue({}); const wrapper = mount(<App />); // 2. 找到按钮并触发点击事件 wrapper.find('#buttonOption1').simulate('click'); // 3. 如果submitChoice是异步函数,需要等待异步流程完成 await new Promise(resolve => setImmediate(resolve)); wrapper.update(); // 4. 断言Mock函数被调用 expect(mockSubmit).toHaveBeenCalled(); // 5. 测试完成后清理Mock mockSubmit.mockRestore(); }); });
情况2:submitChoice是通过props传入的函数
如果组件是通过props接收submitChoice,那你需要直接创建Mock函数作为props传入组件:
import React from 'react'; import App from './App'; import { mount } from 'enzyme'; describe('App', () => { it('should call the submitChoice method on click', () => { // 1. 创建Mock函数 const mockSubmitChoice = jest.fn(); // 2. 将Mock函数作为props传入组件 const wrapper = mount(<App submitChoice={mockSubmitChoice} />); // 3. 触发按钮点击 wrapper.find('#buttonOption1').simulate('click'); // 4. 断言Mock函数被调用 expect(mockSubmitChoice).toHaveBeenCalled(); }); });
情况3:submitChoice是从外部模块导入的函数
如果submitChoice是从API模块导入的,比如import { submitChoice } from './api',那你需要Mock整个模块:
import React from 'react'; import App from './App'; import { mount } from 'enzyme'; import { submitChoice } from './api'; // Mock整个API模块 jest.mock('./api', () => ({ submitChoice: jest.fn().mockResolvedValue({}) })); describe('App', () => { it('should call the submitChoice method on click', async () => { const wrapper = mount(<App />); wrapper.find('#buttonOption1').simulate('click'); await new Promise(resolve => setImmediate(resolve)); expect(submitChoice).toHaveBeenCalled(); }); });
2. 确认渲染方式是否正确
如果你用了shallow渲染,而#buttonOption1按钮在组件的子组件中,shallow不会渲染子组件,导致找不到按钮元素。这种情况下应该换成mount渲染,它会渲染整个组件树。
3. 处理异步函数的时序问题
如果submitChoice是异步函数(比如包含API调用),测试代码会在异步操作完成前执行断言,导致断言失败。你需要等待异步流程结束后再断言:
- 可以用
async/await配合setImmediate(如上例) - 或者使用enzyme的
waitForState(如果你的组件会根据API调用结果更新state):await waitForState(wrapper, state => state.someStateKey !== initialValue);
额外检查点
- 确认按钮的选择器
#buttonOption1是否正确,比如有没有拼写错误,或者按钮的id是否真的是这个值。 - 检查按钮的点击事件绑定是否正确,比如是不是绑定了
onClick={() => this.submitChoice()},而不是其他函数。
内容的提问来源于stack exchange,提问作者Oliver
相关产品推荐
相关产品推荐

