React Testing Library waitFor报MutationObserver构造函数错误
React Testing Library 中waitFor抛出MutationObserver is not a constructor错误修复
问题场景
编写DraftPage组件单元测试时,需等待页面加载完成、删除图标渲染后再执行后续点击、断言步骤,调用waitFor方法时触发运行错误。
相关代码
导入部分
import { render, screen, waitFor, fireEvent } from '../../../TestMocks/CustomRender'; import DraftPage from '../DraftPage'; import '@testing-library/jest-dom'; import React from 'react';
DraftPage组件核心逻辑
{ loader ? <Grid data-testid="full page loader"> <CircularProgress /> </Grid> : <Grid> <IconButton disabled={item.notSynced}> <DeleteIcon data-testid="draft delete icon" onClick={()=>{console.log('btn click')}} /> </IconButton> </Grid> }
测试用例代码
it("delete a card number reduce", async () => { render(<DraftPage />); const loader = screen.getAllByTestId("full page loader") await waitFor(() => expect(screen.getByTestId("draft delete icon")).toBeInTheDocument()) fireEvent.click(screen.getByTestId("draft delete icon")); expect(screen.getByText("draft delete dialog")).toBeInTheDocument(); })
报错输出
FAIL src/Components/Draft/__Test__/DraftPage.test.js (11.746s) √ renders draft page (193ms) × delete a card number reduce (55ms) ● delete a card number reduce TypeError: MutationObserver is not a constructor 75 | const loader = screen.getAllByTestId("full page loader") 76 | console.log(loader) > 77 | await waitFor(() => expect(screen.getByTestId("draft delete icon")).toBeInTheDocument()) | ^ 78 | fireEvent.click(screen.getByTestId("draft delete icon")); 79 | expect(screen.getByText("draft delete dialog")).toBeInTheDocument(); 80 | }) at node_modules/@testing-library/dom/dist/wait-for.js:106:18 at waitFor (node_modules/@testing-library/dom/dist/wait-for.js:39:10) at node_modules/@testing-library/dom/dist/wait-for.js:188:54 at node_modules/@testing-library/react/dist/pure.js:59:22 at node_modules/@testing-library/react/dist/act-compat.js:63:24 at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:21856:12) at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:929:14) at node_modules/@testing-library/react/dist/act-compat.js:62:20 at asyncAct (node_modules/@testing-library/react/dist/act-compat.js:40:14) at Object.asyncWrapper (node_modules/@testing-library/react/dist/pure.js:58:35) at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:188:35) at Object.<anonymous> (src/Components/Draft/__Test__/DraftPage.test.js:77:11)
错误根因
waitFor 内部依赖浏览器原生API MutationObserver 监听DOM树变化,在检测到DOM更新时重新执行传入的断言回调。该报错说明当前测试运行环境(多为Jest+jsdom组合)没有提供MutationObserver的实现,常见触发场景:
- Jest 28及以上版本默认不再内置jsdom测试环境,未手动安装配置时运行在纯Node环境,缺少DOM相关API
- 使用的jsdom版本过低,未内置MutationObserver实现
- 测试启动配置未正确加载DOM相关polyfill
修复方案
按以下优先级排查处理:
- 配置Jest使用jsdom测试环境
Jest 28+版本需要先单独安装jsdom环境包:
然后在npm i -D jest-environment-jsdomjest.config.js中添加配置:module.exports = { // 其余原有配置 testEnvironment: 'jsdom', } - 确认
@testing-library/jest-dom的导入位置
确保该包在所有测试代码执行前导入(一般放在jest的setupFiles配置文件中统一引入),它会自动补全测试环境缺失的常用DOM API,避免兼容问题。 - 优化测试逻辑
现有测试只等待删除图标出现,没有显式处理加载态,容易出现时序问题,可以用waitForElementToBeRemoved先等待加载态消失,逻辑更稳定:import { render, screen, waitFor, fireEvent, waitForElementToBeRemoved } from '../../../TestMocks/CustomRender'; it("delete a card number reduce", async () => { render(<DraftPage />); // 等待全屏加载组件消失 await waitForElementToBeRemoved(() => screen.getByTestId("full page loader")) // 加载完成后删除图标已稳定渲染,可直接操作 fireEvent.click(screen.getByTestId("draft delete icon")); expect(screen.getByText("draft delete dialog")).toBeInTheDocument(); })
内容的提问来源于stack exchange,提问作者ash1102
相关产品推荐
相关产品推荐

