You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 08:45:01