未使用setImmediate却触发ReferenceError错误的原因排查
问题排查与解决方案
错误原因分析
这个ReferenceError: setImmediate is not defined错误,本质是测试环境(jsdom + Jest)与WebSocket相关依赖的兼容性问题:
- 你的App组件在渲染时大概率初始化了WebSocket连接,而jsdom没有原生WebSocket实现,依赖了
xmlhttprequest-ssl作为polyfill - 该polyfill使用了Node.js的
setImmediate方法,但Create React App的Jest测试环境没有全局暴露这个方法 - 测试时无后端WebSocket服务,连接失败触发错误流程,最终暴露了这个未定义方法的问题
具体解决办法
方法1:Mock WebSocket对象(最推荐)
既然你的测试只需要验证组件渲染,不需要实际的WebSocket连接,直接在测试文件中mock全局WebSocket,避免触发真实连接逻辑:
import React from 'react'; import { render } from '@testing-library/react'; import App from './App'; // 全局mock WebSocket,阻止真实连接 global.WebSocket = jest.fn(() => ({ onopen: jest.fn(), onmessage: jest.fn(), onclose: jest.fn(), send: jest.fn(), close: jest.fn() })); test('renders the app', async () => { window.HTMLElement.prototype.scrollIntoView = function() {}; const {container} = await render(<App />); expect(container.querySelector('h1')).toHaveTextContent('Welcome to ChitChat') });
方法2:添加setImmediate的polyfill
如果需要保留部分WebSocket逻辑,可在测试环境中补全setImmediate定义,在测试文件开头或项目根目录的src/setupTests.js中添加:
// 给测试环境添加setImmediate的polyfill global.setImmediate = global.setImmediate || ((callback) => setTimeout(callback, 0));
方法3:修改组件逻辑适配测试
将WebSocket的初始化逻辑抽离,支持测试时注入模拟实例,比如:
// App.js中抽离WebSocket创建逻辑 export const createWebSocket = () => new WebSocket('ws://your-url'); function App() { const ws = useMemo(() => createWebSocket(), []); // ...其他逻辑 } // 测试时替换createWebSocket import { createWebSocket } from './App'; jest.mock('./App', () => ({ ...jest.requireActual('./App'), createWebSocket: jest.fn(() => ({ /* mock实例 */ })) }));
内容的提问来源于stack exchange,提问作者Animus
相关产品推荐
相关产品推荐

