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

Next.js12(SWC替代Babel)中Jest与React测试库动态导入测试失败

解决Next.js 12(SWC)+ Jest测试动态导入组件的报错问题

问题背景

技术栈:

  • NextJS 12(使用SWC,不依赖Babel)
  • React 18
  • Jest + React Testing Library

测试使用next/dynamic动态导入组件的页面时,触发如下错误:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

原因分析

Jest默认无法正确解析Next.js的dynamic异步导入逻辑,在SWC编译环境下,动态导入的组件在测试阶段无法被同步加载,最终返回undefined导致渲染失败。

可行解决方案

方案1:Mock next/dynamic实现同步加载

在测试文件头部或全局jest.setup.js中添加mock代码,让动态导入强制同步返回组件:

jest.mock('next/dynamic', () => ({
  __esModule: true,
  default: (importFunc) => {
    // 直接解析异步导入的Promise,同步返回组件默认导出
    const component = importFunc();
    return component.then(mod => mod.default);
  },
}));

方案2:添加测试环境的静态导入分支

修改页面组件代码,通过环境变量判断,在测试环境下跳过动态导入,直接静态加载组件:

import styles from '@/pages/index.module.css';
import dynamic from 'next/dynamic';

// 测试环境用静态导入,避免动态加载的 Jest 兼容问题
const Hello = process.env.NODE_ENV === 'test'
  ? require('../components/Hello').default
  : dynamic(() => import('../components/Hello'));

export default function Home() {
  return (
    <div className={styles.container}>
      {/* 原有页面代码 */}
      <Hello />
    </div>
  );
}

方案3:配置SWC支持动态导入解析

在jest.config.js中调整SWC的转换规则,确保其能正确处理动态导入语法:

module.exports = {
  transform: {
    '^.+\\.(ts|tsx)$': ['@swc/jest', {
      jsc: {
        parser: {
          syntax: 'typescript',
          jsx: true,
          dynamicImport: true, // 启用动态导入解析
        },
        transform: {
          react: {
            runtime: 'automatic',
          },
        },
      },
    }],
  },
};

验证测试

调整后重新运行测试,确认组件能被正常渲染:

import { render, screen } from '@testing-library/react';
import Home from '@/pages/index';

describe('Home', () => {
  it('renders heading and Hello component', () => {
    render(<Home />);

    const heading = screen.getByRole('heading', {
      name: /welcome to next\.js!/i,
    });
    expect(heading).toBeInTheDocument();
    
    expect(screen.getByText('Hello')).toBeInTheDocument();
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:12:35