使用Jest测试React组件时Wrapper未渲染组件的问题排查
问题:React组件Jest测试中MockComponent的Wrapper为空导致测试失败
我在为React组件编写Jest测试时,为了清晰观察测试逻辑创建了MockComponent,但Wrapper始终为空,测试失败。测试代码如下:
import React, { useState } from "react"; import { shallow, render } from "enzyme"; import MapComp from "../components/MapComp"; import { MapContainer, Polyline } from "react-leaflet"; describe("MapComp", () => { it("renders a Polyline component with the correct props", () => { const mockData = { positions: [ [55.79104, -3.96177], [55.79093, -3.9621], // ... add more coordinates here ], name: "Cold morning run", activityType: "Run", duration: "6.43", date: "2022-11-30T07:46:36Z", distance: 1623, // ... add more properties here }; const MockComponent = () => { const [isLoading, setIsLoading] = useState(true); setTimeout(() => { setIsLoading(false); }, 1000); return !isLoading ? ( <div> <MapContainer center={getInitPosition()} zoom={15} scrollWheelZoom={false} style={props.style} > <TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url={ props.mapStyle ? props.mapStyle : "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" } /> {!Array.isArray(props.activityData) && !props.activityData.polylines && ( <Polyline positions={props.activityData.positions} pathOptions={{ color: mapColors[props.activityData.activityType], }} > <Marker position={[ props.activityData.positions[0][0], props.activityData.positions[0][1], ]} > <Popup>{props.activityData.name}</Popup> </Marker> </Polyline> )} {Array.isArray(props.activityData.polylines) && props.activityData.polylines.length > 1 && props.activityData.polylines.map((activity, idx) => ( <Polyline key={idx} positions={activity.positions} pathOptions={{ color: mapColors[activity.activityType] }} > {props.showMarkers ? ( <Marker position={[ activity.positions[0][0], activity.positions[0][1], ]} > <Popup> <div> <h2>{"Name: " + activity.name}</h2> </div> </Popup> </Marker> ) : ( <div></div> )} </Polyline> ))} </MapContainer> </div> ) : ( <div> <p>Loading...</p> </div> ); }; const wrapper = shallow(<MockComponent />); const polylineData = wrapper.find("Polyline"); expect(polylineData).toHaveLength(1); expect(polylineData.prop("positions")).toEqual(mockData.positions); expect(polylineData.prop("pathOptions")).toEqual({ color: "blue" }); }); });
测试报错显示:expect(received).toHaveLength(expected),received的长度为0,不符合预期的1。
问题排查与解决方案
核心问题点
- 初始加载状态未跳过:MockComponent的
useState初始值为true,shallow渲染不会等待setTimeout执行,初始渲染的是Loading状态,自然找不到Polyline组件。 - 未传递必要Props:MockComponent中使用了
props.activityData、props.style等属性,但渲染时没有传入任何Props,导致后续渲染Polyline的条件不满足。 - 依赖缺失:代码中
getInitPosition()、mapColors、TileLayer、Marker、Popup均未定义或导入,会导致组件报错无法正常渲染。 - Shallow渲染限制:Enzyme的
shallow只会渲染组件本身,不会深入渲染MapContainer内部的子组件,所以无法找到其中的Polyline。
修复步骤
直接控制加载状态
模拟useState让初始状态为false,跳过Loading阶段:jest.mock('react', () => ({ ...jest.requireActual('react'), useState: jest.fn(() => [false, jest.fn()]) }));传递必要Props
渲染MockComponent时传入测试所需的activityData:const wrapper = shallow(<MockComponent activityData={mockData} />);补全依赖或Mock第三方组件
- 导入缺失的react-leaflet组件:
import { TileLayer, Marker, Popup } from "react-leaflet"; - 定义缺失的函数和变量:
const getInitPosition = () => [55.79104, -3.96177]; const mapColors = { Run: "blue" }; - 或者Mock整个react-leaflet组件,避免依赖真实实现:
jest.mock('react-leaflet', () => ({ MapContainer: ({ children }) => <div>{children}</div>, Polyline: ({ ...props }) => <div {...props} />, TileLayer: () => <div />, Marker: ({ children }) => <div>{children}</div>, Popup: ({ children }) => <div>{children}</div> }));
- 导入缺失的react-leaflet组件:
改用Mount渲染
如果需要深入渲染子组件,替换shallow为mount:import { mount } from 'enzyme'; // ... const wrapper = mount(<MockComponent activityData={mockData} />);
内容的提问来源于stack exchange,提问作者program.exe
相关产品推荐
相关产品推荐

