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

useEffect中动态import @vimeo/player的Jest测试失败排查

问题根因

你的推测完全准确:测试失败核心是动态import()为异步操作,测试逻辑未等待播放器初始化流程完成就提前触发了事件。
你打印playerRef.current能看到已注册的事件列表,是控制台延迟求值特性导致的:console.log输出对象时不会立刻序列化内容,等你手动展开日志查看时,异步导入早就执行完毕,因此能看到绑定完成的事件;但测试代码执行trigger()的时间点,动态import的Promise还未决议,Player实例未完成初始化、事件处理器还未绑定到实例上,触发事件自然不会触发预期的状态更新。
另外Mock实现存在小瑕疵:构造函数初始化this.events = new Map(),但on方法直接用对象属性赋值的方式存储handler,未调用Map的set方法,逻辑不一致容易埋下隐性问题。

正确测试实现

核心逻辑是在触发测试事件前,先等待动态导入、实例初始化、事件绑定全流程完成,推荐用waitFor做状态等待,实现简单且时序稳定:

// 先把MockPlayer定义提到外层,方便做类型断言
jest.mock('@vimeo/player', () => class MockPlayer {
  constructor() {
    // 修正events初始化逻辑,直接用普通对象即可,不需要Map
    this.events = {};
    this.destroy = jest.fn();
  }
  on(event, handler) {
    this.events[event] = handler;
  }
  trigger(event) {
    this.events[event]?.();
  }
  getVideoTitle() {
    return Promise.resolve('title.mp4');
  }
});

test.each([
  ['loaded', 'isLoading', true, false],
  ['bufferstart', 'isBuffering', false, true],
  ['play', 'isPlaying', false, true],
])('event: %s should set state: %s from %s to %s',
  async (event, state, valueBefore, valueAfter) => {
    const { result } = renderHook(useVideoPlayer, {
      initialProps: { playerRef: ref, playerConfig },
    });

    // 等待动态导入完成、Player实例初始化、事件绑定完毕
    await waitFor(() => {
      expect(result.current.playerRef.current).toBeInstanceOf(MockPlayer);
    });

    expect(result.current[state]).toEqual(valueBefore);

    act(() => {
      result.current.playerRef.current.trigger(event);
    });

    expect(result.current[state]).toEqual(valueAfter);
  });

React 18 配套的测试工具中,waitFor内部已自动包裹act,如果触发事件后的状态更新是同步的,不需要额外再写waitForNextUpdate。

额外优化建议
  • 修复Hook的useEffect依赖:当前依赖数组仅传入[playerRef],playerConfig变化时不会重新初始化播放器,建议将playerConfig加入依赖数组,同时在清理函数中先缓存实例引用再销毁,避免闭包拿到过期ref值。
  • 修正Mock的destroy实现:原实现中调用destroy才会返回jest.fn,无法正确追踪销毁方法的调用情况,直接将destroy赋值为jest.fn即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:03:24