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

如何使用Jest测试对接DynamoDB的Express Serverless接口

解决方案

你遇到的问题本质是单元测试默认对接了云端DynamoDB导致的,和你用Express框架没有冲突,以下两种方案都可以解决:

方案一:Mock DynamoDB客户端(单元测试首选,轻量无需额外服务)

直接用Jest模拟AWS SDK的DynamoDB DocumentClient实例,拦截数据库请求返回预设值,不需要真的连接任何远端/本地数据库,适合纯业务逻辑验证。

操作步骤:

  1. 首先在测试文件中Mock aws-sdk 模块,同时建议Mock异步生成urlId的nanoid方法,避免随机值影响断言:
const request = require('supertest');
const AWS = require('aws-sdk');
const { nanoid } = require('nanoid/async');
const app = require('../app');

// Mock nanoid固定返回值
jest.mock('nanoid/async', () => ({
  nanoid: jest.fn().mockResolvedValue('test1234')
}));

// Mock DynamoDB DocumentClient的方法
const mockGet = jest.fn();
const mockTransactWrite = jest.fn();
AWS.DynamoDB.DocumentClient = jest.fn(() => ({
  get: mockGet,
  transactWrite: mockTransactWrite
}));

// 每个测试用例前清空mock调用记录
beforeEach(() => {
  mockGet.mockClear();
  mockTransactWrite.mockClear();
});
  1. 针对你当前的测试用例,补充不同场景的返回模拟:
// 场景1:数据库中不存在该长链,需要新增记录
test('Should convert new url from anonymous user ', async () => {
  // 模拟get方法返回空结果(不存在该长链)
  mockGet.mockImplementation((params, callback) => {
    callback(null, {});
  });
  // 模拟transactWrite执行成功
  mockTransactWrite.mockImplementation((params, callback) => {
    callback(null);
  });

  const res = await request(app)
    .post('/anon-ops/convert')
    .send({
      longUrl: 'https://google.com',
    })
    .expect(201);
  
  // 可选:断言返回值符合预期
  expect(res.body.convertedUrl).toBe('https://xxxxxxxxxxxx/test1234');
  // 可选:断言DynamoDB方法被调用的参数符合预期
  expect(mockGet).toHaveBeenCalledWith(expect.objectContaining({
    Key: { userId: 'anonymous', originalUrl: 'https://google.com' }
  }), expect.any(Function));
});

// 场景2:数据库中已存在该长链,直接返回已有短链
test('Should return existed converted url for duplicate longUrl', async () => {
  // 模拟get方法返回已有记录
  mockGet.mockImplementation((params, callback) => {
    callback(null, {
      Item: {
        userId: 'anonymous',
        originalUrl: 'https://google.com',
        convertedUrl: 'https://xxxxxxxxxxxx/exist123'
      }
    });
  });

  const res = await request(app)
    .post('/anon-ops/convert')
    .send({
      longUrl: 'https://google.com',
    })
    .expect(201);
  
  expect(res.body.convertedUrl).toBe('https://xxxxxxxxxxxx/exist123');
  // 验证这种场景下不会调用写入方法
  expect(mockTransactWrite).not.toHaveBeenCalled();
});

方案二:使用本地DynamoDB做集成测试(适合需要验证真实数据库操作的场景)

如果需要真的运行DynamoDB读写逻辑验证完整性,可以本地启动DynamoDB Local服务,测试时将SDK的连接指向本地实例。

操作步骤:

  1. 本地启动DynamoDB Local,推荐用Docker一键启动:
    docker run -p 8000:8000 amazon/dynamodb-local
  2. 在Jest的全局配置文件(或测试文件开头)修改AWS SDK的默认配置,指向本地DynamoDB:
const AWS = require('aws-sdk');
AWS.config.update({
  region: 'local',
  endpoint: 'http://localhost:8000',
  accessKeyId: 'fakeAccessKey',
  secretAccessKey: 'fakeSecretKey'
});
  1. 测试前提前在本地DynamoDB中创建和线上同名的测试表,测试完成后可以清空测试数据,不会影响线上环境。

注意:如果你的代码中已经硬编码了DynamoDB实例的配置,可以把实例化逻辑抽成可配置的公共模块,测试时直接替换配置即可,不需要修改业务代码。

内容的提问来源于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.06 23:00:05