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

Jest结合TypeScript如何测试window对象上定义的函数

问题原因

测试不通过的核心问题有3个:

  • 模块加载时机问题:Api.ts在顶层作用域直接执行const verifier = window.Verifier,这个赋值发生在模块被import的阶段,早于测试用例中mock window对象的时机。后续测试中修改window上的Verifier属性,不会影响模块内已经缓存的verifier常量,实际调用时取到的是模块加载时的undefined值,自然不会触发mock的request方法。
  • Mock方式不合理:通过jest.spyOn(window, "window", "get")直接替换整个window对象的返回值,会丢失window上原有的内置属性和jest依赖的全局API,容易触发额外报错。
  • 异步断言时机错误:fetchData是返回Promise的异步方法,测试中调用后没有等待方法执行完成就直接断言,会出现断言执行早于内部逻辑的问题。
修复步骤

1. 调整Api.ts中Verifier的读取时机

删除顶层缓存的verifier常量,改为在方法调用时动态读取window上的Verifier,保证能拿到测试阶段注入的mock值:

import "./global.d";

export class Api {
  constructor(private readonly id: string) {}
  public fetchData() {
    return new Promise<object>((resolve, reject) => {
      // 动态读取window.Verifier,不要在模块顶层缓存
      window.Verifier.request({
        request: {
          id: this.id
        },
        onSuccess: (data: object) => {
          resolve(data);
        },
        onFailure: () => {
          reject("Error!");
        }
      });
    });
  }
}

如果想减少重复书写window.Verifier,可以在类中增加一个getter做动态取值:

private get verifier() {
  return window.Verifier;
}

后续方法中直接使用this.verifier.request()即可。

2. 调整测试用例的Mock逻辑和异步处理

不需要spy整个window对象,直接给window.Verifier赋值mock对象即可,同时等待异步方法执行完成后再做断言:

import { Api } from "./Api";

// 保存全局Verifier的原始值,测试结束后恢复
const originalVerifier = window.Verifier;

describe("Test Apis", () => {
  afterEach(() => {
    // 恢复全局状态,清除mock
    window.Verifier = originalVerifier;
    jest.clearAllMocks();
  });

  it("should call the request method with correct params", async () => {
    const mockedRequest = jest.fn((payload) => {
      // 模拟成功回调,让Promise正常落定
      payload.onSuccess({ res: "ok" });
    });
    // 直接挂载mock的Verifier到window上
    window.Verifier = {
      request: mockedRequest
    } as any;

    const api = new Api("123");
    // 等待异步方法执行完成
    const res = await api.fetchData();
    
    // 验证调用逻辑
    expect(mockedRequest).toHaveBeenCalledTimes(1);
    expect(mockedRequest).toHaveBeenCalledWith(expect.objectContaining({
      request: { id: "123" }
    }));
    expect(res).toEqual({ res: "ok" });
  });
});

注意:确保你的jest配置中测试环境设置为jsdom(jest默认配置就是jsdom),否则测试环境中不存在window对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:09:18