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

如何使用Jest模拟DynamoDB的Promise返回(不依赖第三方库)

无第三方库模拟DynamoDB Promise返回方案

问题根源

你当前的测试Mock是针对回调形式的DynamoDB调用实现的,但业务代码中使用的是AWS SDK提供的.promise()链式调用语法,Mock结构与实际调用逻辑不匹配,所以无法正常模拟返回。

核心实现逻辑

不需要引入任何第三方依赖,仅需对齐AWS SDK的调用结构即可:调用DynamoDB操作方法(get/transactWrite等)后会返回一个带有promise方法的对象,调用该方法会返回对应结果的Promise实例,按照这个结构写Mock就行。

修正后的测试代码

const request = require('supertest');

describe('Test for Authenticated Url', () => {
  beforeEach(() => {
    jest.resetModules();
    // 固定nanoid返回值,方便断言
    jest.mock('nanoid/async', () => ({
      nanoid: jest.fn(() => Promise.resolve('test1234'))
    }));
  });

  test('应该返回已存在的转换链接', async () => {
    const mockedDocumentClient = {
      get: jest.fn(),
      transactWrite: jest.fn(),
    };

    const mockedDynamoDB = {
      DocumentClient: jest.fn(() => mockedDocumentClient),
    };
    jest.doMock('aws-sdk', () => ({ DynamoDB: mockedDynamoDB }));

    // 模拟get方法返回已有记录
    mockedDocumentClient.get.mockImplementation(() => ({
      promise: () => Promise.resolve({
        Item: {
          convertedUrl: 'xyz',
        },
      })
    }));
    // 模拟transactWrite方法执行成功
    mockedDocumentClient.transactWrite.mockImplementation(() => ({
      promise: () => Promise.resolve()
    }));

    const app = require('../app');
    const response = await request(app).post('/').send({
      longUrl: 'https://google.com',
    });
    expect(response.body).toMatchObject({ convertedUrl: 'xyz' });
    expect(response.statusCode).toBe(201);
  });

  test('新链接应该生成并返回新转换链接', async () => {
    const mockedDocumentClient = {
      get: jest.fn(),
      transactWrite: jest.fn(),
    };

    const mockedDynamoDB = {
      DocumentClient: jest.fn(() => mockedDocumentClient),
    };
    jest.doMock('aws-sdk', () => ({ DynamoDB: mockedDynamoDB }));

    // 模拟get方法返回空(无匹配记录)
    mockedDocumentClient.get.mockImplementation(() => ({
      promise: () => Promise.resolve({})
    }));
    mockedDocumentClient.transactWrite.mockImplementation(() => ({
      promise: () => Promise.resolve()
    }));

    const app = require('../app');
    const response = await request(app).post('/').send({
      longUrl: 'https://google.com',
    });
    expect(response.body).toMatchObject({ 
      convertedUrl: 'https://trimify.awssensei.tk/test1234' 
    });
    expect(response.statusCode).toBe(201);
  });

  test('Dynamo报错时应该返回500错误', async () => {
    const mockedDocumentClient = {
      get: jest.fn(),
    };

    const mockedDynamoDB = {
      DocumentClient: jest.fn(() => mockedDocumentClient),
    };
    jest.doMock('aws-sdk', () => ({ DynamoDB: mockedDynamoDB }));

    // 模拟get方法抛出异常
    mockedDocumentClient.get.mockImplementation(() => ({
      promise: () => Promise.reject(new Error('连接失败'))
    }));

    const app = require('../app');
    const response = await request(app).post('/').send({
      longUrl: 'https://google.com',
    });
    expect(response.statusCode).toBe(500);
    expect(response.body.error).toBe('Unknown Server Error, Please Trimify Again!');
  });
});

补充说明

如果需要同时兼容回调和promise两种调用方式,可以在mock实现里加判断:有传回调就执行回调,同时返回带promise方法的对象即可,不需要修改现有业务逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:39:03