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

使用Jest与TypeScript进行React Canvas组件单元测试时mount()报错及函数调用验证问题

解决Enzyme + Jest测试React Canvas组件时的mount报错及函数调用验证问题

让我们一步步拆解你的问题,先弄清楚错误的根源,再给出可行的解决方案:

错误原因分析

1. mount时的Cannot read properties of undefined (reading 'child')错误

这个错误的核心是你在beforeEach中对props.draw的赋值完全错误:

props = { draw: jest.fn().getMockImplementation };

jest.fn().getMockImplementation是一个方法引用,不是一个可执行的mock函数。当Enzyme尝试渲染组件并调用这个"函数"时,内部会出现异常,导致渲染失败。正确的做法是直接用jest.fn()创建一个可以被追踪调用的mock函数。

2. mock useEffect的错误写法

你尝试直接调用useEffect.getMockImplementation()是完全错误的:useEffect是React的内置钩子,你需要通过jest.spyOn来mock它,而不是直接调用这个不存在的方法。不过实际上,在这个测试场景中我们根本不需要mock useEffect——我们要测试的是组件的正常行为:当组件挂载时,useEffect会自动执行并调用传入的draw函数。

完整修正后的测试代码

以下是可以正常运行的测试代码,同时能正确验证draw函数是否被调用:

import React from 'react'
import { configure, shallow, mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import GraphicCanvas, { IGraphicCanvas } from "./GraphCanvas";
import { drawCircle } from "./DrawCircle"

configure({ adapter: new Adapter() });

describe("GraphicCanvas", () => {
  let props: IGraphicCanvas;

  beforeEach(() => {
    // 1. 创建一个可追踪的mock函数作为draw属性
    props = { draw: jest.fn() };

    // 2. Mock canvas的getContext方法,避免测试环境中canvas API的兼容性问题
    jest.spyOn(HTMLCanvasElement.prototype, 'getContext').mockReturnValue({
      fillStyle: '',
      beginPath: jest.fn(),
      arc: jest.fn(),
      fill: jest.fn()
    } as unknown as CanvasRenderingContext2D);
  });

  // 重置所有mock,避免测试用例之间的污染
  afterEach(() => {
    jest.restoreAllMocks();
  });

  it("renders without crashing", () => {
    shallow(<GraphicCanvas draw={drawCircle} />);
  });

  it("calls the draw function passed in props when component mounts", () => {
    // 挂载组件
    mount(<GraphicCanvas {...props} />);

    // 断言draw函数被调用过至少一次
    expect(props.draw).toHaveBeenCalled();

    // 可选:进一步断言draw函数被传入了Canvas上下文对象
    expect(props.draw).toHaveBeenCalledWith(expect.any(CanvasRenderingContext2D));
  });
});

关键修正点说明

  1. 正确创建mock函数:
    用jest.fn()创建的mock函数可以被Jest追踪调用次数、调用参数等,完全满足你的测试需求,替代之前错误的getMockImplementation引用。

  2. Mock Canvas API:
    在测试环境中,canvas.getContext('2d')可能返回null或者存在兼容性问题,我们通过jest.spyOn mock这个方法,返回一个模拟的Canvas上下文对象,确保组件内的useEffect能正常执行到props.draw(context)这一步。

  3. 不需要mock useEffect:
    我们的测试目标是验证组件的正常业务逻辑——当组件挂载时,是否会调用传入的draw函数。保持useEffect的原生行为,才能真实模拟组件的运行状态,测试结果更可靠。

额外提示

如果你想直接测试drawCircle函数是否被调用(而不是用mock函数),可以这样修改测试用例:

it("calls drawCircle when component mounts", () => {
  // Spy on drawCircle函数,追踪它的调用
  const drawCircleSpy = jest.spyOn(require("./DrawCircle"), 'drawCircle');
  
  mount(<GraphicCanvas draw={drawCircle} />);
  
  expect(drawCircleSpy).toHaveBeenCalled();
  drawCircleSpy.mockRestore();
});

这样可以直接验证真实的drawCircle函数是否被组件调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:22:32