React Testing Library 如何mock组件内部函数 使测试调用模拟函数而非原函数
问题本质
你在测试中定义的mock函数和MyForm组件内部的testFunction是完全独立的两个变量,没有任何关联,组件默认只会调用自身内部定义的函数,因此你的mock函数始终不会被触发。
方案一:改造组件将提交函数作为Props传入(推荐)
这是最符合React组件设计规范、可维护性最高的方案,既方便测试,也能让组件适用更多复用场景。
修改后的MyForm组件代码
import React from 'react'; // 注意:React组件名必须首字母大写,原写法小写不符合规范 export default function MyForm({ onSubmit = () => {} }) { return ( <div> <form onSubmit={onSubmit}> <input type="text" /> <button type="submit" data-testid="submit-button">submit</button> </form> </div> ); }
修改后的测试代码
import React from 'react'; import { render, cleanup, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import MyForm from './MyForm'; afterEach(cleanup); test('my form', () => { const testFunction = jest.fn(); // 将mock函数作为onSubmit属性传入组件 const { getByTestId } = render(<MyForm onSubmit={testFunction} />); const myButton = getByTestId('submit-button'); expect(myButton.tagName).toBe('BUTTON'); fireEvent.click(myButton) expect(testFunction).toHaveBeenCalledTimes(1) });
方案二:Mock组件内部导出的函数(无需修改组件对外API)
如果你不想调整组件的对外参数,可以将内部提交函数抽离导出后再做mock,适合不需要对外暴露提交逻辑的场景。
修改后的MyForm组件代码
import React from 'react'; // 抽离提交函数并单独导出 export const internalSubmit = () => { console.log('hello from inside'); } export default function MyForm() { return ( <div> <form onSubmit={internalSubmit}> <input type="text" /> <button type="submit" data-testid="submit-button">submit</button> </form> </div> ); }
修改后的测试代码
import React from 'react'; import { render, cleanup, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import MyForm, { internalSubmit } from './MyForm'; afterEach(cleanup); // Mock组件导出的internalSubmit函数 jest.mock('./MyForm', () => ({ ...jest.requireActual('./MyForm'), internalSubmit: jest.fn() })) test('my form', () => { const { getByTestId } = render(<MyForm />); const myButton = getByTestId('submit-button'); expect(myButton.tagName).toBe('BUTTON'); fireEvent.click(myButton) expect(internalSubmit).toHaveBeenCalledTimes(1) });
小提示:如果提交事件触发后有页面跳转等默认行为干扰测试,可以在提交回调中添加
e.preventDefault()处理。
内容的提问来源于stack exchange,提问作者TommyD
相关产品推荐
相关产品推荐

