如何使用Jest Mock带参数的函数?Mock不生效原函数仍执行如何解决?
问题根因
- 导入时序错误
ES 模块的导入语句存在提升特性,会在所有代码执行前先完成导入。你在测试代码中先导入了<AddForm/>组件,此时B.js已经提前导入并持有了原始add方法的引用,后续你对A.js的 mock 操作无法影响已经被B.js捕获的函数引用,因此调用的还是原生方法。 - 导出导入不匹配
你提供的A.js中使用的是export add命名导出,而B.js中使用import add from './A'默认导入,本身存在语法错误,需要先统一两者的导出导入规则。
修复步骤
第一步:统一导出导入规则
二选一即可:
- 方案A:将
A.js改为默认导出
// A.js function add(a, b, c) { return a + b + c } export default add;
- 方案B:将
B.js改为命名导入
// B.js import { add } from './A';
第二步:修正测试代码
推荐使用jest.mock方案,不受导入提升影响,稳定性更高:
// B.test.js // 这行代码会被jest自动提升到所有导入之前执行,优先完成mock jest.mock('./A', () => ({ // 如果是命名导出,替换为 add: jest.fn(() => 100) default: jest.fn(() => 100) })) import AddForm from './B'; // 如果是命名导出,替换为 import { add } from './A' import add from './A'; describe('<AddForm/>', () => { test('should call add with correct parameters', () => { render(<AddForm />); // 验证add被调用参数符合预期 expect(add).toHaveBeenCalledWith(1, 2, 3); // 验证mock返回值生效 expect(add.mock.results[0].value).toBe(100); }); });
如果需要保留jest.spyOn的写法,需要用require手动控制导入时序,避免导入提升的影响:
// B.test.js const helpers = require('./A'); // 如果是命名导出,把'default'改为'add' const addSpy = jest.spyOn(helpers, 'default').mockImplementation(() => 100); const AddForm = require('./B').default; describe('<AddForm/>', () => { afterEach(() => { addSpy.mockRestore(); }); test('should render all elements', () => { render(<AddForm />); expect(addSpy).toHaveBeenCalledWith(1,2,3); }); });
内容的提问来源于stack exchange,提问作者Niranj Rajasekaran
相关产品推荐
相关产品推荐

