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

Jest测试集成react-leaflet的React组件报export语法错误如何解决

问题现象

测试集成react-leaflet的React组件时,触发如下语法错误:

C:\digital-booking-ui\node_modules\react-leaflet\lib\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { useMap, useMapEvent, useMapEvents } from './hooks.js';
                                                                                  ^^^^^^

SyntaxError: Unexpected token 'export'

  1 | import React from "react";
  2 | import { makeStyles } from "@material-ui/core";
> 3 | import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet";
    | ^
  4 |
  5 | const Map = () => {
  6 |   const classes = useStyles();

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
  at Object.<anonymous> (src/components/accomodation/Map.js:3:1)

所有引入react-leaflet的组件在测试渲染时都会触发该错误,示例测试代码如下:

import { render, screen, prettyDOM } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect'
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { ThemeProvider } from '@material-ui/core';
import theme from "./theme";

let component = null;

beforeEach(() => {
    component = render(
      <BrowserRouter>
        <ThemeProvider theme={theme}>
          <App />
        </ThemeProvider>
      </BrowserRouter>
    );
}
);

test('render App', () => {
  expect(component).toBeTruthy();
});

问题本质:Jest默认运行在CommonJS环境,且默认不会转译node_modules下的依赖,而react-leaflet v3+版本为原生ES模块格式,使用ESM的export语法,直接被Jest加载时就会抛出语法错误。

修复步骤

1. 修改Jest转译配置,将react-leaflet相关依赖加入转译白名单

不要只单独添加react-leaflet,它的内部依赖@react-leaflet/core、底层依赖leaflet高版本也都是ESM格式,需要全部加入转译范围。
如果项目使用独立的jest.config.js配置文件,修改transformIgnorePatterns字段:

// jest.config.js
module.exports = {
  // 保留原有其他配置
  transform: {
    // 确保js/jsx文件走babel-jest转译
    '^.+\\.(js|jsx)$': 'babel-jest'
  },
  transformIgnorePatterns: [
    // 排除react-leaflet相关依赖,不忽略转译
    'node_modules/(?!(react-leaflet|@react-leaflet|leaflet)/)'
  ]
}

如果是未eject的Create React App项目,直接在package.json的jest字段下添加上述transformIgnorePatterns配置即可。
如果使用craco/react-app-rewired等配置覆盖工具,对应修改jest配置项即可。

2. 配置Babel支持ESM转译

确保项目的Babel配置(.babelrc/babel.config.js)包含@babel/preset-env,配置示例:

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-react'
  ]
}

3. (可选,稳定性更高)测试环境直接mock react-leaflet组件

地图组件依赖浏览器环境的尺寸API、地理定位API,jsdom环境没有完整实现这些能力,即使转译通过也可能触发其他运行时错误。单元测试不需要验证第三方库本身的逻辑,可以直接在测试全局setup文件中mock react-leaflet的导出,彻底规避ESM加载问题和DOM依赖问题:
在src/setupTests.js(Jest默认的setup文件)中添加:

// 先保留原有setup逻辑,比如@testing-library/jest-dom的导入
jest.mock('react-leaflet', () => ({
  MapContainer: ({ children }) => <div data-testid="map-container">{children}</div>,
  TileLayer: () => <div data-testid="tile-layer" />,
  Marker: ({ children }) => <div data-testid="marker">{children}</div>,
  Popup: ({ children }) => <div data-testid="popup">{children}</div>,
  useMap: () => ({
    setView: jest.fn(),
    fitBounds: jest.fn(),
    getZoom: jest.fn(() => 13)
  }),
  useMapEvent: jest.fn(),
  useMapEvents: jest.fn(() => ({}))
}))

// mock leaflet默认图标,避免静态资源路径报错
jest.mock('leaflet', () => {
  const actual = jest.requireActual('leaflet')
  return {
    ...actual,
    Icon: {
      Default: {
        mergeOptions: jest.fn(),
        prototype: { options: {} }
      }
    }
  }
})

4. 清空Jest缓存后重新运行测试

配置修改完成后执行以下命令清空缓存,避免旧的缓存文件导致错误复现:

npx jest --clearCache
常见踩坑点
  • 只把react-leaflet加入转译白名单,漏了@react-leaflet/core依赖,依然会报同样的Unexpected token 'export'错误
  • 配置修改后没有清空Jest缓存,旧的未转译文件被缓存加载
  • Babel配置没有覆盖node_modules下的上述依赖,导致转译不生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:48:31