使用Jest测试React项目时react-leaflet导入为undefined致元素类型无效
React-Leaflet模块在Jest测试中显示undefined导致「无效元素类型」错误的解决办法
我在使用Jest测试React项目时遭遇「无效元素类型」错误,发现从react-leaflet导入的模块在Jest环境中显示为undefined。测试代码、App组件代码及报错截图如下:
测试代码
import { render, screen } from '@testing-library/react'; import App from './App'; test('renders learn react link', () => { render( <App /> ) const linkElement = screen.getByText("map-btn"); expect(linkElement).toBeInTheDocument(); });
App组件代码
import React, { useState, useEffect } from "react" import { MapContainer, TileLayer, Marker, Popup, useMap, Circle } from 'react-leaflet' import L from 'leaflet' function App(){ return ( <div className={'col-md-8'}> <div> <MapContainer center={[25.033671, 121.564427]} zoom={17} style={{height: '100vh'}} > <TileLayer attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <Marker position={[25.033671, 121.564427]}> <Popup>current position</Popup> </Marker> </MapContainer> </div> </div> ) } export default App
报错截图

问题原因
react-leaflet依赖浏览器环境的DOM API,而Jest运行在Node.js环境中,没有真实的浏览器DOM;同时react-leaflet的部分模块可能未被Jest正确转译,导致导入后返回undefined,最终触发「无效元素类型」错误。
解决办法
Mock react-leaflet组件:在测试文件顶部添加mock,用简单React元素替代真实地图组件,避免环境不兼容问题:
jest.mock('react-leaflet', () => ({ MapContainer: ({ children }) => <div data-testid="map-container">{children}</div>, TileLayer: () => null, Marker: ({ children }) => <div>{children}</div>, Popup: ({ children }) => <div>{children}</div>, useMap: () => ({ setView: jest.fn() }), Circle: () => null }));配置Jest转译依赖模块:在
jest.config.js中修改transformIgnorePatterns,确保leaflet和react-leaflet被转译:module.exports = { // 其他已有配置 transformIgnorePatterns: [ '/node_modules/(?!leaflet|react-leaflet)/' ] };模拟Leaflet全局对象:Leaflet依赖全局的
L对象,在测试中mock所需的Leaflet方法:jest.mock('leaflet', () => ({ ...jest.requireActual('leaflet'), marker: jest.fn(() => ({ addTo: jest.fn() })) }));修正测试逻辑:原测试代码中查找的"map-btn"文本在App组件中不存在,调整为测试实际存在的元素,比如Popup中的文本:
test('renders map popup text', () => { render(<App />); const popupText = screen.getByText("current position"); expect(popupText).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Penny Chang
相关产品推荐
相关产品推荐

