Тестирование асинхронного SQS sendMessage - PullRequest
0 голосов
/ 18 января 2019

У меня есть асинхронная лямбда, которая выполняет асинхронный запрос sendMessage SQS. Очередь SQS - это стандартная очередь, а не FIFO, просто для пояснения.

Вот пример кода (без несоответствующей части логики):

exports.functionHandler = async (event, context, callback) => {
    try {
        let parsedBody = JSON.parse(event.Records[0].body);
        let modifiedBody = await doStuff(parsedBody);

        let sqsPayload = {
            MessageBody: JSON.stringify(modifiedBody),
            QueueUrl: my-queue-url
        };

        await sqs.sendMessage(sqsPayload).promise();

        callback(null, utils.respondSuccess("Done"));
    } catch (err) {
        // Handle error

        callback(null, utils.respondError(err));
    }
};

const doStuff = async payload => {
    // Do stuff 
}

Довольно просто.

Теперь проблема: я пытаюсь протестировать эту функцию с помощью пакета aws-sdk-mock. Вот как я заглушал функцию sendMessage, когда лямбда не была асинхронной, а функция sendMessage использовала обратный вызов:

it("an awesome title for my test", async () => {
    let payload = {
        Records: [
            // Data here
        ]
    };

    AWS.mock("SQS", "sendMessage", (param, callback) => {
        let response = {
            ResponseMetadata: {
                RequestId: "test-request-id"
            },
            MD5OfMessageBody: "a892e8d8589e97ca92fb70020f01c16c",
            MessageId: "test-message-id"
        };

        callback(null, response);
    });

    await app.functionHandler(payload, {}, (err, result) => {
        let parsedBody = JSON.parse(result.body);
        expect(parsedBody.message).to.be.equal("Done");
        // More stuff
    });

    AWS.restore();
});

Если я использую этот тест, функция sendMessage выдает следующую ошибку:

sendMessage returned an invalid MD5 response. Got "undefined", expecting "a892e8d8589e97ca92fb70020f01c16c".

Я не уверен, как проверить sendMessage асинхронно. Я не против принять другой пакет, если он поможет мне выполнить работу.

Может кто-нибудь помочь?

Большое спасибо

1 Ответ

0 голосов
/ 19 января 2019

Я не использовал aws-sdk-mock, но, видимо, в вашем макете вы используете обратный вызов, а в лямбда-обработчике это асинхронный вызов. Я использую proxyquire для насмешливых зависимостей. Вот пример:

functionHandler.js

Не нужно использовать callback и context во время Lambda Node8.10.

let AWSSQS = require('aws-sdk/clients/sqs');
let sqs = new AWSSQS();

exports.functionHandler = async (event) => {

  // No need to use callback when Lambda runtime is 8.10.
  try {

    let parsedBody = JSON.parse(event.Records[0].body);
    let modifiedBody = await doStuff(parsedBody);

    let sqsPayload = {
      MessageBody: JSON.stringify(modifiedBody),
      QueueUrl: my-queue-url
    };

    await sqs.sendMessage(sqsPayload).promise();

    return utils.respondSuccess('Done');
  } catch (err) {
    throw utils.respondError(err);
  }
};

test.spec.js

В значительной степени говорит само за себя. Вы определяете объект с именем зависимости как свойство.

const proxyquire = require('proxyquire');

let app = require('path/to/function');

describe('SQS', () => {

  it("an awesome title for my test", async (done) => {

    const app = proxyquire(app, {
      'aws-sdk/clients/sqs': function() {
        this.sendMessage = (params) => {
          return {
            promise: () => {
              return Promise.resolve({
                ResponseMetadata: {
                  RequestId: 'test-request-id'
                },
                MD5OfMessageBody: 'a892e8d8589e97ca92fb70020f01c16c',
                MessageId: 'test-message-id'
              });
            }
          }
        }
      }
    });

    let payload = {
      Records: [
        // Data here
      ]
    };

    const data = await app.functionHandler(payload);
    let parsedBody = JSON.parse(data.body);
    expect(parsedBody.message).to.be.equal("Done");
    done();
  });
});
...