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

如何在Jest测试中抛出错误触发React组件的Error Boundary?

React Error Boundary单元测试:触发错误的最优方案

问题场景

现有包含Error Boundary的组件结构如下:

return (
  <ErrorBoundary
    componentDidCatch(error, info) {
      handleError(error, info);
    }
  >
    <MyComponent>
      // 组件其余内容及子组件
    </MyComponent>
  </ErrorBoundary>
)

手动测试时,通过在useEffect中执行throw new Error('Error')可正常触发Error Boundary,但Jest单元测试中,尝试直接编写同步抛错组件(如下)未成功,且认为添加onError prop的方案不够直观,寻求更优实现:

test('Error Boundary', () => {
    const ThrowError = () => {
      throw new Error('Test');
    };

  render(
    <ChildOfMyComponent>
    <ThrowError />
  );

// 其他逻辑

可行解决方案

1. 在 useEffect 中异步抛错(最贴合手动测试逻辑)

同步渲染阶段的错误会被Jest直接捕获导致测试失败,无法传递给Error Boundary。改用useEffect在组件挂载后抛错,属于更新阶段错误,能正确触发Error Boundary:

import { useEffect } from 'react';
import { render } from '@testing-library/react';

test('Error Boundary 捕获子组件异步错误', () => {
  const mockHandleError = jest.fn();

  // 定义挂载后抛错的组件
  const ThrowErrorOnMount = () => {
    useEffect(() => {
      throw new Error('Test Error');
    }, []);
    return null;
  };

  render(
    <ErrorBoundary componentDidCatch={mockHandleError}>
      <MyComponent>
        <ThrowErrorOnMount />
      </MyComponent>
    </ErrorBoundary>
  );

  // 断言错误处理函数被调用
  expect(mockHandleError).toHaveBeenCalled();
});

2. 触发组件内部现有错误逻辑

直接利用MyComponent或其子组件本身的错误分支(比如传入非法props、触发错误状态),比单独写抛错组件更贴近真实业务场景:

test('Error Boundary 捕获MyComponent内部错误', () => {
  const mockHandleError = jest.fn();

  render(
    <ErrorBoundary componentDidCatch={mockHandleError}>
      {/* 传入会触发MyComponent内部错误的props */}
      <MyComponent criticalData={undefined} />
    </ErrorBoundary>
  );

  expect(mockHandleError).toHaveBeenCalled();
});

3. 用 Jest Spy 替换组件方法抛错

如果需要测试特定方法抛错的场景,用jest.spyOn替换目标方法使其抛出错误:

test('Error Boundary 捕获MyComponent方法执行错误', () => {
  const mockHandleError = jest.fn();
  // 假设MyComponent原型上有fetchData方法
  const spy = jest.spyOn(MyComponent.prototype, 'fetchData')
    .mockImplementation(() => { throw new Error('Fetch Failed'); });

  render(
    <ErrorBoundary componentDidCatch={mockHandleError}>
      <MyComponent />
    </ErrorBoundary>
  );

  expect(mockHandleError).toHaveBeenCalled();
  // 测试后清理spy
  spy.mockRestore();
});

为什么同步抛错组件不生效?

React在初始同步渲染阶段的错误不会被Error Boundary捕获,这类错误会直接被Jest拦截导致测试失败。只有在组件更新阶段(比如useEffect执行、事件回调触发、状态更新后的渲染)抛出的错误,才会被Error Boundary的componentDidCatch捕获。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:12:46