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

Node.js/TypeScript中Jest无法mock类构造函数问题求解

Jest mock @azure/identity 中 ClientSecretCredential 构造函数不生效的解决方案

核心问题原因

你的代码存在三个直接导致mock失效、断言不命中的问题:

  • jest.mock 位置错误:Jest会自动将所有jest.mock调用提升到文件最顶部、import语句之前执行,你把它嵌套在describe块内部,会导致mock覆盖逻辑无法正确绑定到导入的ClientSecretCredential引用上。
  • 断言逻辑错误:构造函数实例化时抛出错误是同步行为,.rejects仅用于捕获Promise异步拒绝场景,用在这里永远无法命中同步抛出的错误。
  • mock逻辑未做入参匹配:你需要根据传入的三个入参(tenantId、clientId、clientSecret)判断抛出对应异常,无法自动根据参数区分错误类型。

正确实现代码

import { ClientSecretCredential } from "@azure/identity";

// jest.mock必须放在文件顶层,Jest会自动提升到import前执行
jest.mock("@azure/identity", () => ({
  ClientSecretCredential: jest.fn()
}));

describe("ClientSecretCredential described", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe("Azure identity", () => {
    it("Should throw an error on incorrectly provided tenantId, clientId or clientSecret", () => {
      // 动态设置mock构造函数实现,根据入参抛出对应错误
      (ClientSecretCredential as jest.Mock).mockImplementation(
        (tenantId: string, clientId: string, clientSecret: string) => {
          if (tenantId !== "valid_tenant_id") {
            throw new Error("Invalid tenant id is provided");
          }
          if (clientId !== "valid_client_id") {
            throw new Error("Invalid client id is provided");
          }
          if (clientSecret !== "valid_client_secret") {
            throw new Error("Invalid client secret is provided");
          }
          // 正常实例化场景返回符合类型的mock对象即可
          return {} as ClientSecretCredential;
        }
      );

      // 同步抛错不需要加.rejects,直接包裹实例化逻辑断言抛出内容
      expect(() => new ClientSecretCredential("some id", "some id", "some id"))
        .toThrowError("Invalid tenant id");
    });
  });
});

优化提示

  • TypeScript项目中可以用jest.mocked(ClientSecretCredential)获取带完整类型提示的mock对象,省去手动类型断言的步骤:
    const MockedClientSecretCredential = jest.mocked(ClientSecretCredential);
    // 后续直接调用MockedClientSecretCredential.mockImplementation即可,无类型报错
    
  • 不需要在jest.mock初始化时写死mock实现,只需要在顶层将目标类替换为jest.fn(),可以在不同测试用例、beforeEach钩子中动态设置不同的实现逻辑,适配不同测试场景。
  • 禁止在describe/it块内部声明jest.mock,除了作用域提升问题外,还容易触发模块缓存异常导致mock偶发不生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:15:29