如何使用Jest和React Testing Library测试React的Error Boundary
测试思路存在的问题
- 你在测试顶层直接写
const error = throw new Error("An error occurred")会在组件渲染前直接抛出未捕获的错误,直接导致测试崩溃,根本走不到后续的渲染逻辑。 - 函数组件本身不存在
simulateError()这种自定义方法,你没办法直接调用它让组件内部抛错。 - 你原来的
SimpleComponent没有任何抛错逻辑,正常渲染永远不会触发Error Boundary。
正确实现方案
有两种常用实现方式,你可以根据需求选择:
方案1:修改原组件增加抛错控制(侵入性最小)
给SimpleComponent加一个可选props控制是否抛出错误,仅在测试环境下开启即可:
// 原组件修改 const SimpleComponent = ({ throwTestError = false }) => { if (throwTestError) { throw new Error("Test trigger error") } return <h1>Hello, world</h1> }
然后编写测试代码即可,注意要临时屏蔽console.error,避免React打印组件错误日志干扰测试输出:
describe("Error Boundary", () => { // 测试前屏蔽console.error,测试后恢复 beforeAll(() => { jest.spyOn(console, "error").mockImplementation(() => {}) }) afterAll(() => { console.error.mockRestore() }) test("子组件抛错时正常渲染 fallback UI", () => { // 直接渲染ErrorBoundary,传入会抛错的子组件即可 render( <ErrorBoundary FallbackComponent={ErrorFallback}> <SimpleComponent throwTestError /> </ErrorBoundary> ) expect(screen.getByText("There was an error!")).toBeInTheDocument() }) })
方案2:不需要修改原组件,测试时模拟子组件
如果你不想改动业务代码,可以在测试里用Jest模拟SimpleComponent,让它渲染时直接抛错:
describe("Error Boundary", () => { beforeAll(() => { jest.spyOn(console, "error").mockImplementation(() => {}) }) afterAll(() => { console.error.mockRestore() }) test("子组件抛错时正常渲染 fallback UI", () => { // 模拟SimpleComponent返回抛错的组件,路径替换为你实际的组件路径 jest.mock("./componentPath", () => ({ ...jest.requireActual("./componentPath"), SimpleComponent: () => { throw new Error("Test trigger error") } })) // 引入TopLevelComponent必须放在mock之后,路径替换为你实际的组件路径 const { TopLevelComponent } = require("./componentPath") render(<TopLevelComponent />) expect(screen.getByText("There was an error!")).toBeInTheDocument() }) })
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

