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

如何Mock AWS SDK类以编写signUp函数的单元测试?

如何Mock AWS SDK v3的Cognito客户端进行单元测试

问题背景

现有一个基于AWS SDK v3的用户注册函数signUp,源码如下:

import {
  SignUpCommand,
  CognitoIdentityProviderClient,
} from "@aws-sdk/client-cognito-identity-provider";
import { createClientForDefaultRegion } from "../../libs/utils/util-aws-sdk.js";

const signUp = async ({ clientId, username, password, email }) => {
  const client = createClientForDefaultRegion(CognitoIdentityProviderClient);

  const command = new SignUpCommand({
    ClientId: clientId,
    Username: username,
    Password: password,
    UserAttributes: [{ Name: "email", Value: email }],
  });

  return client.send(command);
};

编写单元测试时尝试Mock AWS SDK,但测试仍调用真实实现,原Mock代码存在问题:

jest.mock('@aws-sdk/client-cognito-identity-provider', () => {
  return {
    CognitoIdentityProvider: class {
      send() {
        return new Promise((resolve, reject) => {
          resolve(expected)
        })
      }
    },
    SignUpCommand: class {}
  }
})

错误分析

  1. 类名不匹配:源码中使用的是CognitoIdentityProviderClient,但Mock里写的是CognitoIdentityProvider,导致Mock未生效
  2. 参数传递错误:signUp接收的是单个对象参数,但测试用例里直接传了四个独立参数,函数无法正确解析
  3. 变量作用域问题:Mock工厂函数内部无法访问测试用例里的expected变量
  4. 未Mock自定义工具函数:createClientForDefaultRegion是自定义封装的函数,需要同步Mock它的返回值

正确实现方案

步骤1:修正AWS SDK的Mock

确保Mock的类名与源码一致,同时用jest.fn()来模拟send方法的返回值:

import { signUp } from './path-to-your-signUp-file';
import { createClientForDefaultRegion } from "../../libs/utils/util-aws-sdk.js";

// Mock AWS SDK
jest.mock('@aws-sdk/client-cognito-identity-provider', () => {
  const mockSend = jest.fn();
  return {
    CognitoIdentityProviderClient: jest.fn(() => ({
      send: mockSend
    })),
    SignUpCommand: jest.fn((input) => input) // 保留命令参数以便后续验证
  };
});

// Mock自定义工具函数
jest.mock('../../libs/utils/util-aws-sdk.js', () => ({
  createClientForDefaultRegion: jest.fn((ClientClass) => new ClientClass())
}));

步骤2:编写正确的测试用例

调整参数传递为对象形式,同时验证Mock的调用情况:

describe('cognito', () => {
  it('should sign up a user', async () => {
    // 定义预期返回值
    const expected = { UserConfirmed: true, UserSub: '1234567890' };
    // 获取Mock的send方法
    const mockSend = require('@aws-sdk/client-cognito-identity-provider').CognitoIdentityProviderClient.mock.results[0].value.send;
    // 设置send方法的异步返回值
    mockSend.mockResolvedValue(expected);

    // 调用signUp,传入正确格式的对象参数
    const result = await signUp({
      clientId: '42',
      username: 'tony.stark@example.com',
      password: '1@m1r0nm@n',
      email: 'tony.stark@example.com'
    });

    // 验证返回值符合预期
    expect(result).toMatchObject(expected);
    // 验证SignUpCommand是否被传入正确参数
    expect(require('@aws-sdk/client-cognito-identity-provider').SignUpCommand).toHaveBeenCalledWith({
      ClientId: '42',
      Username: 'tony.stark@example.com',
      Password: '1@m1r0nm@n',
      UserAttributes: [{ Name: "email", Value: 'tony.stark@example.com' }]
    });
    // 验证send方法是否被调用
    expect(mockSend).toHaveBeenCalled();
  });
});

关键说明

  • 对于AWS SDK v3的客户端,需要Mock客户端类的构造函数,使其返回带有send方法的模拟对象
  • 自定义工具函数createClientForDefaultRegion必须Mock,否则会创建真实的客户端实例
  • 使用mockResolvedValue模拟异步返回,比手动创建Promise更简洁
  • 可通过验证SignUpCommand的参数,确保业务逻辑传递的参数符合预期

内容的提问来源于stack exchange,提问作者Code-Apprentice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:35:22