【问题标题】:How to unit-test a AWS Lambda use lambda-local with mocha?如何对 AWS Lambda 使用 lambda-local 和 mocha 进行单元测试?
【发布时间】:2026-02-21 17:30:01
【问题描述】:

背景

我正在开发一个使用 Serverless 框架和 serverless-appsync-plugin 构建的项目。我实现了一个端点(AWS Lambda)来处理 Appsync 通过 graphQL 生成的所有请求。端点会将请求路由到相应的函数来执行操作。

问题

现在我已经开发了大约 10 多个操作,我想自动化单元测试的过程。为简单起见,我决定在本地将单个端点作为 lambda 运行以进行所有测试(而不是运行 appsync-offline)。

所以,我使用 lambda-localmocha。但是,根据我从 lambda 得到的响应,我无法让测试用例失败。

it('db should have a user of uId: 123',  async function () {
  lambdaLocal.execute({
    event: makeUserEvent({userId: '123'}),
    callbackWaitsForEmptyEventLoop: false,
    lambdaPath,
    callback: function(err, data) {
      if(err) {
        console.log(1)
        expect.fail(null, null, 'You are not supposed to be here') //should fail here
      } else {
        console.log(2)
        // some checking here, may fail or may not fail
        expect.fail(null, null, 'return fail if the userId is 234') //should fail here too
      }
    }
  });
  console.log(3)
})

在这两种情况下,我都希望它失败,callback('failed', null)callback(null, 'success') 的测试用例都不会失败。

那么,让 lambda-local 测试用例失败的正确方法是什么?

【问题讨论】:

    标签: unit-testing lambda aws-lambda mocha.js


    【解决方案1】:

    在您的代码中,测试完成时没有 mocha 注册 lambdaLocal.execute 中的断言失败。所以总会过去的。

    您可以返回一个承诺,或者等待lambdalocal.execute,然后执行您的断言,而不是使用回调参数。

    例如(使用 Promises):

    it('db should have a user of uId: 123',  function () {
      return lambdaLocal.execute({
        event: makeUserEvent({userId: '123'}),
        callbackWaitsForEmptyEventLoop: false,
        lambdaPath })
     .then(
        (data) => {
            console.log(2)
            // some checking here, may fail or may not fail
            expect.fail(null, null, 'return fail if the userId is 234') //should fail here
        },
        (err) => {
            console.log(1)
            expect.fail(null, null, 'You are not supposed to be here') //should fail here
        })
    }
    

    或者更改传递给it 的函数的签名以获取一个附加参数(通常称为done),然后mocha 将使用该参数传递一个函数,该函数可用于表示测试已完成。请参阅mocha documentation 了解更多信息。

    【讨论】:

    • 首先,代码有效。但是,我还是有些不明白。 1. 在我的代码中,console.log(1) 在 console.log(3) 之前运行。这是否意味着返回回调在外部块之前执行? 2.你是如何将原来的回调样式转换为承诺样式的?更准确地说,你怎么知道 lambda.execute 是一个承诺,你可以在它之后链接一个 .then() ? 3.怎么知道.then()里面的第一个参数是数据,第二个参数是错误?
    • 1.: 问题不在于执行顺序,而是断言抛出的错误没有被 mocha 捕获,因为它在一个独立的回调中(这就是我们返回承诺的原因)。 2.:我通过查看lambda-local 的测试文件找到了该信息。 3.:这就是Promise.then 的工作原理,参见mdn