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

如何为使用Azure存储文件共享、服务总线的代码编写Jest单元测试

可行测试方案

一共两类实现路径,都不需要连接真实Azure服务,本地开发和GitHub CI流水线都能直接跑,适配Jest+NestJS的技术栈。

方案一:纯Jest Mock实现(适合单元测试,零额外依赖)

这是单元测试场景下最轻量的方案,不需要启动任何额外服务,测试执行速度最快。核心逻辑是通过Jest的mock能力,替换掉@azure/storage-file-share、@azure/service-bus SDK中实际发起网络请求的客户端实现,返回你预设的测试数据,只验证业务逻辑本身的正确性。

Azure File Share 测试实现

如果你在NestJS中是通过依赖注入的方式注入ShareClient、ShareFileClient实例,直接在测试模块中替换为mock实例即可:

// files.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { ShareFileClient } from '@azure/storage-file-share';
import { FilesService } from './files.service';

describe('FilesService', () => {
  let service: FilesService;
  let mockFileClient: jest.Mocked<ShareFileClient>;

  beforeEach(async () => {
    // 构造mock客户端,只需要实现你业务代码里实际调用的方法
    mockFileClient = {
      downloadFileToBuffer: jest.fn(),
      uploadFile: jest.fn(),
      deleteFile: jest.fn(),
    } as unknown as jest.Mocked<ShareFileClient>;

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        FilesService,
        { provide: 'SHARE_FILE_CLIENT', useValue: mockFileClient }
      ],
    }).compile();

    service = module.get<FilesService>(FilesService);
  });

  it('should correctly get file content from share', async () => {
    const testContent = Buffer.from('test file content');
    // 模拟SDK返回结果
    mockFileClient.downloadFileToBuffer.mockResolvedValue([testContent]);
    
    const res = await service.getFileContent('test/path.txt');
    expect(res).toEqual(testContent);
    expect(mockFileClient.downloadFileToBuffer).toHaveBeenCalledTimes(1);
  });
});

如果不想逐个方法手动构造mock,可以直接用jest.mock()全局mock整个SDK包,所有客户端调用都会自动替换为mock函数:

jest.mock('@azure/storage-file-share', () => {
  const mockFileClient = {
    downloadFileToBuffer: jest.fn(),
    uploadFile: jest.fn()
  };
  return {
    ShareClient: jest.fn().mockImplementation(() => ({
      getFileClient: jest.fn().mockReturnValue(mockFileClient)
    })),
    ShareFileClient: jest.fn()
  }
});

Azure Service Bus 测试实现

逻辑和File Share完全一致,mock你业务用到的ServiceBusClient、消息发送器、接收器的方法即可:

jest.mock('@azure/service-bus', () => {
  const mockSender = {
    sendMessages: jest.fn().mockResolvedValue(undefined),
    close: jest.fn().mockResolvedValue(undefined)
  };
  const mockReceiver = {
    receiveMessages: jest.fn().mockResolvedValue([{ body: { orderId: 1, status: 'paid' } }]),
    close: jest.fn().mockResolvedValue(undefined)
  };
  return {
    ServiceBusClient: jest.fn().mockImplementation(() => ({
      createSender: jest.fn().mockReturnValue(mockSender),
      createReceiver: jest.fn().mockReturnValue(mockReceiver),
      close: jest.fn().mockResolvedValue(undefined)
    }))
  }
});

写测试用例的时候,只需要断言对应方法有没有被正确调用、入参是否符合预期、业务逻辑有没有正确处理SDK返回的结果即可。
这个方案的缺点是需要自己维护mock的方法和返回结构,和真实服务的行为可能存在细微差异,适合纯单元测试场景。

方案二:本地模拟器实现(适合集成测试,行为贴近真实服务)

如果你需要覆盖SDK调用、参数校验、请求流程这类纯mock覆盖不到的逻辑,可以用兼容Azure SDK的本地模拟器,不需要连接真实云服务,本地和CI都能快速启动。

  • Azure File Share 模拟器:用Azurite,是Azure官方维护的开源存储模拟器,完整支持File Share、Blob、Queue的所有接口,和官方SDK完全兼容。启动后直接用模拟器默认的连接串初始化SDK客户端即可,不需要修改业务代码。本地可以直接通过npm全局安装启动,CI环境可以直接用npm命令启动,也可以用容器启动。
    启动命令参考:azurite --silent --sharePort 10000
  • Azure Service Bus 模拟器:用社区维护的开源Service Bus内存模拟器,兼容官方SDK的核心接口,支持队列、主题、订阅的消息收发逻辑,启动后用默认连接串即可连接,CI环境用容器一行命令就能启动。
    这个方案的优点是不需要写大量mock代码,SDK交互逻辑和真实服务几乎一致,测试可信度更高;缺点是测试启动速度比纯mock慢一点,但整体耗时完全在可接受范围内。

GitHub Actions流水线适配

两种方案都不需要给流水线配置Azure账号权限:

  • 纯mock方案:直接在流水线中执行npm run test即可,和普通单元测试没有区别。
  • 模拟器方案:在执行测试的步骤前,加一步启动对应模拟器的步骤即可,GitHub托管运行器默认自带node和docker环境,不需要额外配置。注意测试环境下要把服务连接串改成模拟器的本地地址,建议通过环境变量注入,不要硬编码。

注意:如果用模拟器方案,不需要做特殊的网络配置,模拟器都是跑在本地环回地址,不会发起公网请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 01:42:37