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

为何Sinon Stub未生效仍发起AWS外部调用?JS Lambda测试问题

AWS Lambda单元测试中Sinon Stub失效问题排查

业务代码(index.js)

// index.js
const AWS = require("aws-sdk");
const getParam = async (path) => {
  const ssm = new AWS.SSM();
  const params = {
    Name: path,
    WithDecryption: false
  }
  
  // 原代码存在笔误:param应为params
  const result = await ssm.getParameter(params).promise();
  const value = result['Parameter']['Value']
  console.log("@@", value);
  return value;
}

module.exports = { getParam }; // 需补充导出,否则测试无法引入

原测试代码(index.test.js)

// index.test.js
const AWS = require("aws-sdk");
AWS.config.update({ region: 'us-east-1' });

const chai = require('chai');
const expect = chai.expect;
const sinon = require("sinon");

const { getParam } = require('./index.js');

describe("test1", () => {
  // 语法错误:用if替代了Mocha的it测试用例语法
  if('testing', async () => {
    // 错误1:创建实例时少了new;错误2:该实例与业务代码内新建的实例完全独立
    const ssm = AWS.SSM();
    // 参数匹配错误:指定匹配"testing",但实际调用传入的是"Hello"
    sinon.stub(ssm, "getParameter").withArgs("testing")
      .resolve({ Parameter: { Value: "TESTING VALUE FROM PARAM STORE" } });

    const res = await getParam("Hello");

    console.log(res);
    // 断言无效:未验证实际返回值,仅对比两个相同字符串
    expect("TESTING VALUE FROM PARAM STORE").to.equal("TESTING VALUE FROM PARAM STORE");
  })
})

问题分析

导致Stub失效、触发真实AWS调用的核心原因:

  • Stub对象不匹配:测试中Stub的是局部创建的ssm实例,但业务代码每次调用getParam都会新建new AWS.SSM()实例,两个实例完全独立,Stub无法作用到业务代码的实例。
  • 语法与参数错误:用if替代it导致测试逻辑异常;Stub指定的匹配参数与实际调用参数不符,导致Stub不触发。
  • 业务代码笔误:getParameter(param)中的param应为定义好的params,会导致运行时参数错误。
  • 断言无效:未验证函数实际返回值,无法发现逻辑问题。

修正后的测试代码

// index.test.js
const AWS = require("aws-sdk");
const chai = require('chai');
const expect = chai.expect;
const sinon = require("sinon");

const { getParam } = require('./index.js');

describe("getParam函数测试", () => {
  let ssmStub;

  // 每个测试前Stub SSM类的原型方法,确保所有实例都使用Stub
  beforeEach(() => {
    ssmStub = sinon.stub(AWS.SSM.prototype, "getParameter");
  });

  // 测试后恢复Stub,避免影响其他测试
  afterEach(() => {
    ssmStub.restore();
  });

  it("应正确获取模拟的SSM参数值", async () => {
    const mockValue = "TESTING VALUE FROM PARAM STORE";
    const testPath = "Hello";

    // 模拟AWS SDK的promise链式调用
    ssmStub.returns({
      promise: () => Promise.resolve({ Parameter: { Value: mockValue } })
    });

    const res = await getParam(testPath);

    // 验证getParameter是否被传入正确参数
    sinon.assert.calledWith(ssmStub, {
      Name: testPath,
      WithDecryption: false
    });
    // 断言返回值符合预期
    expect(res).to.equal(mockValue);
  });
})

关键修正说明

  • Stub原型方法:通过sinon.stub(AWS.SSM.prototype, "getParameter")Stub类的原型方法,确保所有new AWS.SSM()创建的实例都会使用该Stub。
  • 处理promise链式调用:AWS SDK方法返回带.promise()的对象,因此Stub需返回包含promise方法的对象,该方法返回resolved状态的Promise。
  • 验证调用参数:用sinon.assert.calledWith校验参数组装是否正确,确保业务逻辑符合预期。
  • 有效断言:直接验证函数返回值,确保逻辑正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:30:56