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

使用React Testing Library测试自定义组件下载链接点击事件时,onDownload方法未被调用,求解决方法

React Testing Library测试自定义组件下载链接点击事件时,onDownload方法未被调用,求解决方法

看起来你遇到的核心问题是测试里定义的mock onDownload和组件实际使用的onDownload完全是两个不相关的函数,组件根本没用到你写的mock,所以点击后自然不会有调用记录。我来一步步帮你解决:

先理清楚几个关键问题

  1. 你的组件代码有语法错误:state.[file_id] 应该改成 state.file_id,state[file_name] 改成 state.file_name,不然组件本身运行就会报错。
  2. 组件定义 const CustomModal = (state) => {...} 里的state其实是React组件的props对象,不是Redux的全局state——如果你是想从Redux拿file_id和file_name,组件里应该用useSelector来获取,而不是直接接收state作为props。
  3. 测试里你定义了const onDownload= jest.fn();,但没有把这个mock函数传给组件,组件用的是外部定义的那个onDownload,和你的mock没关系。

具体修复方案

根据onDownload的实际来源,分两种情况处理:

情况1:onDownload是组件的props

如果onDownload是父组件传给CustomModal的props,那我们可以直接在测试里把mock函数传进去:

第一步:修正组件代码
import React from 'react';
import { useSelector } from 'react-redux'; // 用useSelector从Redux拿数据

const CustomModal = ({ onDownload }) => { // 接收onDownload作为props
  // 从Redux获取file_id和file_name
  const { file_id, file_name } = useSelector(state => state.import.state);

  return (
      <div>
          <a href="#"
            onClick={(event) => {
              event.preventDefault();
              onDownload(file_id); // 修正语法错误
            }}
          > {file_name} </a> // 修正语法错误
      </div>
  )
};
第二步:修正测试代码
import React from 'react';
import { Provider } from 'react-redux';
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom';
import { configureStore } from '@reduxjs/toolkit'; // 确保导入configureStore

describe('CustomModal', () => {
  let store;
  let rendered;

  describe('render', () => {
    beforeEach(() => {
      store = configureStore({
        reducer: { // 注意这里应该是reducer,不是你原来的import
          import: (state = {
            state: {
              file_id: 123456789,
              file_name: 'test_file.xlsx',
            },
          }) => state, // 简单的空reducer,保持store结构
        },
      });
    });

    afterEach(() => {
      cleanup();
    });

    it('should call the onDownload when the download link is clicked', () => {
      const mockOnDownload = jest.fn(); // 定义mock函数
      // 把mock函数作为props传给CustomModal
      rendered = render(
         <Provider store={store}>
           <CustomModal onDownload={mockOnDownload} />
         </Provider>,
      );

      fireEvent.click(screen.getByText('test_file.xlsx'));
      expect(mockOnDownload).toHaveBeenCalledTimes(1);
      expect(mockOnDownload).toHaveBeenCalledWith(123456789); // 还可以验证传参是否正确
    });
  });
});

情况2:onDownload是外部导入的函数(比如Redux action)

如果onDownload是从某个文件导入的(比如action creator),那我们可以用jest.mock来mock这个导入:

第一步:组件代码(假设onDownload是导入的action)
import React from 'react';
import { useSelector } from 'react-redux';
import { onDownload } from './actions'; // 导入onDownload action

const CustomModal = () => {
  const { file_id, file_name } = useSelector(state => state.import.state);

  return (
      <div>
          <a href="#"
            onClick={(event) => {
              event.preventDefault();
              onDownload(file_id);
            }}
          > {file_name} </a>
      </div>
  )
};
第二步:修正测试代码
import React from 'react';
import { Provider } from 'react-redux';
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom';
import { configureStore } from '@reduxjs/toolkit';
import { onDownload } from './actions'; // 导入要mock的函数

// mock整个actions模块,让onDownload变成jest mock函数
jest.mock('./actions', () => ({
  onDownload: jest.fn(),
}));

describe('CustomModal', () => {
  let store;
  let rendered;

  describe('render', () => {
    beforeEach(() => {
      store = configureStore({
        reducer: {
          import: (state = {
            state: {
              file_id: 123456789,
              file_name: 'test_file.xlsx',
            },
          }) => state,
        },
      });
      rendered = render(
         <Provider store={store}>
           <CustomModal />
         </Provider>,
      );
    });

    afterEach(() => {
      cleanup();
    });

    it('should call the onDownload when the download link is clicked', () => {
      fireEvent.click(screen.getByText('test_file.xlsx'));
      expect(onDownload).toHaveBeenCalledTimes(1);
      expect(onDownload).toHaveBeenCalledWith(123456789);
    });
  });
});

额外注意点

  • 测试里的configureStore需要确保是正确导入的,如果你用的是redux-toolkit的configureStore,要从@reduxjs/toolkit导入;如果是传统redux的,要从redux导入。
  • 原来的测试里rendered变量没有声明,记得要提前声明let rendered;。
  • 你原来的store配置里写了import: { state: {...} },但configureStore的参数里应该是reducer字段,对应各个reducer函数,我在上面的测试里用了一个简单的空reducer来保持store结构,你可以替换成你实际的reducer。

这样修改后,测试就能正确捕获到onDownload的调用了。

备注:内容来源于stack exchange,提问作者Mar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 14:14:34