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

如何用react-testing-library测试动态导入SVG的Icon组件

解决方案

问题根源

线上环境的打包工具(如Webpack/Vite)已配置SVG转React组件的加载规则,所以require返回合法组件实例;但Jest默认不识别.svg格式的导入,require返回值为undefined,所以始终渲染占位span,该问题和异步加载、ref使用没有任何关系。

具体修复步骤

第一步:安装对应转换工具

如果你的项目用@svgr/webpack处理SVG转组件,安装配套的Jest转换器:

npm install @svgr/jest --save-dev

如果没有使用svgr,可以用通用静态资源stub工具:

npm install jest-transform-stub --save-dev

第二步:修改Jest配置

在jest.config.js或package.json的jest字段中添加SVG转换规则:

  • 使用@svgr/jest的配置:
module.exports = {
  // 保留原有其他配置
  transform: {
    "^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
    "^.+\\.svg$": "@svgr/jest"
  }
}
  • 使用jest-transform-stub的配置:
module.exports = {
  // 保留原有其他配置
  transform: {
    "^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
    "^.+\\.svg$": "jest-transform-stub"
  }
}

第三步:简化测试用例

你添加的定时器逻辑完全多余,SVG导入并非异步操作,直接删除定时器相关代码即可:

it('matches snapshot of each icon', () => {
  const type = 'check';
  const { getByTestId } = render(<Icon type={type} />);
  expect(getByTestId('icon')).toMatchSnapshot();
});

组件优化建议

当前组件里的useState、useEffect逻辑冗余,className可以直接读取props默认值,不需要存入state,简化后组件逻辑更清晰,也不会带来额外的渲染开销:

const Icon: FC<IconProps> = ({ type, onClick, tooltip, className = 'icon' }: IconProps) => {
  const SVG = require(`../../svg/${type}.svg`).default;
  const spanClassName = "svg-icon-wrapper";
  if (SVG) {
    const iconEl = <SVG className={className} onClick={onClick} data-testid="icon" />;
    if (tooltip) {
      const tooltipDelay: [number, number] = [800, 0];
      return (
        <Tooltip title={tooltip.title} delay={tooltip.delay ? tooltipDelay : 0}>
          <i className={spanClassName}>{iconEl}</i>
        </Tooltip>
      );
    }
    return iconEl;
  }
  return <span className={spanClassName} data-testid="span" />;
};

export default Icon;

内容的提问来源于stack exchange,提问作者Tsuina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:57:02