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

为何Jest测试中BroadcastChannel类未定义?

问题原因及解决方案

原因

Jest 运行在 Node.js 环境中,而 BroadcastChannel 是浏览器专属的 Web API,Node.js 本身并未提供这个全局对象。另外你在自定义 Hook 外部直接实例化 BroadcastChannel,这部分代码会在模块加载阶段就执行,此时测试环境还未对该 API 做模拟,因此直接抛出未定义的错误。

解决办法

方案1:全局模拟 BroadcastChannel

在 Jest 的全局配置文件(如 jest.setup.js)中添加对 BroadcastChannel 的模拟:

global.BroadcastChannel = jest.fn(() => ({
  postMessage: jest.fn(),
  onmessage: null,
  close: jest.fn()
}));

然后在 jest.config.js 中配置该文件为测试前置脚本:

module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js'],
  // 其他 Jest 配置项
};

这样所有测试用例执行前都会自动注入这个模拟对象,避免未定义错误。

方案2:在 Hook 内部条件实例化

将 BroadcastChannel 的实例化逻辑移到 Hook 内部,同时判断当前环境是否支持该 API,测试环境下返回模拟对象:

import React from 'react';

export default function useSessionTimeout() {
  const [sessionChannel] = React.useState(() => {
    // 仅在浏览器环境中实例化真实的 BroadcastChannel
    if (typeof BroadcastChannel !== 'undefined') {
      return new BroadcastChannel("session_timeout_channel");
    }
    // 测试环境返回空实现的模拟对象
    return {
      postMessage: () => {},
      onmessage: null,
      close: () => {}
    };
  });

  // 你的会话超时逻辑...

  return { /* 返回需要的方法或状态 */ };
}

这种方式避免了模块加载阶段执行浏览器 API 代码,同时兼容测试环境。

方案3:验证消息逻辑(可选)

如果需要测试消息发送/接收的逻辑,可以在测试用例中自定义模拟实现,以便断言调用:

import { renderHook } from '@testing-library/react';
import useSessionTimeout from './useSessionTimeout';

describe('useSessionTimeout', () => {
  it('should broadcast session timeout message', () => {
    // 自定义模拟的 postMessage 方法
    const mockPostMessage = jest.fn();
    global.BroadcastChannel.mockImplementation(() => ({
      postMessage: mockPostMessage,
      onmessage: null,
      close: jest.fn()
    }));

    // 渲染 Hook
    const { result } = renderHook(() => useSessionTimeout());

    // 触发发送消息的操作(根据你的 Hook 逻辑调整)
    // result.current.triggerSessionTimeout();

    // 断言消息是否正确发送
    expect(mockPostMessage).toHaveBeenCalledWith({ type: 'SESSION_TIMEOUT' });
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 14:18:09