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

如何测试操作AWS DynamoDB的JS方法?解决测试回调与Promise冲突报错

解决AWS Lambda DynamoDB测试报错及无真实调用测试实现

问题分析

你遇到的Error: Resolution method is overspecified.是因为测试用例同时使用了async函数和done回调参数,Mocha不允许这种混合写法。另外,你的DynamoDB Stub方式不对——DocumentClient.put是基于回调的API,不是返回Promise的,还有Handler代码里存在参数缺失的问题。

修复步骤

1. 移除测试用例的done参数

async函数本身会返回Promise,Mocha会自动等待Promise完成,不需要额外传入done回调。

2. 正确Stub DynamoDB的put方法

使用sinon的yields方法模拟回调执行:

  • 模拟成功:sandbox.stub(db, 'put').yields(null, {}),第一个参数为null表示无错误,第二个参数是回调返回值
  • 模拟失败:sandbox.stub(db, 'put').yields(new Error('DB error'), null)

3. 修正Handler中的参数错误

原代码里的params仅包含TableName,缺少Item字段,这会导致真实调用DynamoDB时失败,需要补上该字段。

修正后的完整代码

Handler.js

const uuid = require('uuid');
// 假设db是外部引入的DynamoDB实例
// const AWS = require('aws-sdk');
// const db = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" });

saveUser(userName, logger) {
  const Item = {
    id: uuid.v4(),
    userName,
    ttl: parseInt(Date.now() / 1000) + 900 // 15分钟后过期
  };
  // 补上Item字段
  const params = {
    TableName: "my-table-name",
    Item
  };
  logger.log(`Saving new user name to DynamoDB: ${JSON.stringify(params)}`);

  return new Promise(function(resolve, reject) {
    db.put(params, function(err, _) {
      if (err) {
        logger.exception(`Unable to connect to DynamoDB to create: ${err}`);
        reject({
          statusCode: 404,
          err
        });
      } else {
        logger.log(`Saved data to DynamoDB: ${JSON.stringify(Item)}`);
        resolve({
          statusCode: 201,
          body: Item
        });
      }
    });
  });
}

Handler.spec.js

import AWS from "aws-sdk";
import sinon from 'sinon';
import { expect } from 'chai';
import userHandler from './Handler';

const sandbox = sinon.createSandbox();

describe("user-name-handler", function() {
  let dbPutStub;

  beforeEach(() => {
    // Stub DocumentClient构造函数,返回带模拟put方法的对象
    dbPutStub = sandbox.stub().yields(null, {});
    sandbox.stub(AWS.DynamoDB, 'DocumentClient').returns({
      put: dbPutStub
    });
  });

  afterEach(() => {
    sandbox.restore();
  });

  it("saveUser() 应成功保存用户并返回正确结果", async function() {
    const result = await userHandler.saveUser("Sample User", {
      log: () => {},
      exception: () => {}
    });

    // 验证put方法调用情况
    expect(dbPutStub.calledOnce).to.be.true;
    const callArgs = dbPutStub.firstCall.args[0];
    expect(callArgs.TableName).to.equal("my-table-name");
    expect(callArgs.Item.userName).to.equal("Sample User");

    // 验证返回结果
    expect(result.statusCode).to.equal(201);
    expect(result.body.userName).to.equal("Sample User");
    expect(result.body.ttl).to.be.a('number');
  });

  it("saveUser() 调用DynamoDB失败时应返回错误", async function() {
    // 模拟DB错误
    const testError = new Error("Connection failed");
    dbPutStub.yields(testError, null);

    try {
      await userHandler.saveUser("Sample User", {
        log: () => {},
        exception: () => {}
      });
      expect.fail("应该抛出错误");
    } catch (err) {
      expect(err.statusCode).to.equal(404);
      expect(err.err).to.equal(testError);
    }
  });
});

关键说明

  • 确保Stub的是handler中实际使用的DynamoDB实例,避免因实例不一致导致Stub无效(上述代码直接Stub了DocumentClient构造函数,确保handler创建的实例是模拟对象)
  • 测试时不仅要验证返回结果,还要验证DynamoDB的put方法是否被正确调用,确保业务逻辑符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:10:01