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

使用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='&copy; <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。

修复步骤

  1. 直接控制加载状态
    模拟useState让初始状态为false,跳过Loading阶段:

    jest.mock('react', () => ({
      ...jest.requireActual('react'),
      useState: jest.fn(() => [false, jest.fn()])
    }));
    
  2. 传递必要Props
    渲染MockComponent时传入测试所需的activityData:

    const wrapper = shallow(<MockComponent activityData={mockData} />);
    
  3. 补全依赖或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>
      }));
      
  4. 改用Mount渲染
    如果需要深入渲染子组件,替换shallow为mount:

    import { mount } from 'enzyme';
    // ...
    const wrapper = mount(<MockComponent activityData={mockData} />);
    

内容的提问来源于stack exchange,提问作者program.exe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:37:52