模拟用于NodeJS单元测试的AWS服务

时间:2018-03-22 17:38:43

标签: node.js amazon-web-services mocking

我正在为NodeJS项目设置一些单元测试,但我想知道如何模拟我对AWS服务的使用。我使用的种类繁多:SNS,SQS,DynamoDB,S3,ECS,EC2,Autoscaling等。有没有人对我如何嘲笑它们有什么好的线索?

谢谢!

3 个答案:

答案 0 :(得分:0)

我尝试使用aws-sdk-mock,但无法使其正常运行。我结果只是使用sinon来存根我需要的函数调用。

答案 1 :(得分:0)

我只是花了几个小时尝试使AWS SQS模拟工作正常,没有求助于在功能内导入aws-sdk-mock客户端的aws-sdk要求。

AWS.DynamoDB.DocumentClient的模拟非常简单,但是AWS.SQS的模拟让我很困惑,直到我遇到使用rewire的建议。

我的lambda将错误消息移至SQS FailQueue(而不是让Lambda失败并将消息返回至常规Queue以进行重试,然后在maxRetries之后将DeadLetterQueue返回)。模拟以下SQS方法所需的单元测试:

  • SQS.getQueueUrl
  • SQS.sendMessage
  • SQS.deleteMessage

在尽量包括所有相关部分的同时,我将尽量简化示例代码:

我的AWS Lambda(index.js)的片段:

const AWS = require('aws-sdk');
AWS.config.update({region:'eu-west-1'});
const docClient = new AWS.DynamoDB.DocumentClient();
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
// ...snip

删节的Lambda事件记录(event.json)

{
    "valid": {
        "Records": [{
            "messageId": "c292410d-3b27-49ae-8e1f-0eb155f0710b",
            "receiptHandle": "AQEBz5JUoLYsn4dstTAxP7/IF9+T1S994n3FLkMvMmAh1Ut/Elpc0tbNZSaCPYDvP+mBBecVWmAM88SgW7iI8T65Blz3cXshP3keWzCgLCnmkwGvDHBYFVccm93yuMe0i5W02jX0s1LJuNVYI1aVtyz19IbzlVksp+z2RxAX6zMhcTy3VzusIZ6aDORW6yYppIYtKuB2G4Ftf8SE4XPzXo5RCdYirja1aMuh9DluEtSIW+lgDQcHbhIZeJx0eC09KQGJSF2uKk2BqTGvQrknw0EvjNEl6Jv56lWKyFT78K3TLBy2XdGFKQTsSALBNtlwFd8ZzcJoMaUFpbJVkzuLDST1y4nKQi7MK58JMsZ4ujZJnYvKFvgtc6YfWgsEuV0QSL9U5FradtXg4EnaBOnGVTFrbE18DoEuvUUiO7ZQPO9auS4=",
            "body": "{ \"key1\": \"value 1\", \"key2\": \"value 2\", \"key3\": \"value 3\", \"key4\": \"value 4\", \"key5\": \"value 5\" }",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1536763724607",
                "SenderId": "AROAJAAXYIAN46PWMV46S:steve.goossens@bbc.co.uk",
                "ApproximateFirstReceiveTimestamp": "1536763724618"
            },
            "messageAttributes": {},
            "md5OfBody": "e5b16f3a468e6547785a3454cfb33293",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:eu-west-1:123456789012:sqs-queue-name",
            "awsRegion": "eu-west-1"
        }]
    }
}

节略的单元测试文件(test / index.test.js):

const AWS = require('aws-sdk');
const expect = require('chai').expect;
const LamdbaTester = require('lambda-tester');
const rewire = require('rewire');
const sinon = require('sinon');

const event = require('./event');
const lambda = rewire('../index');

let sinonSandbox;

function mockGoodSqsMove() {
    const promiseStubSqs = sinonSandbox.stub().resolves({});
    const sqsMock = {
        getQueueUrl: () => ({ promise: sinonSandbox.stub().resolves({ QueueUrl: 'queue-url' }) }),
        sendMessage: () => ({ promise: promiseStubSqs }),
        deleteMessage: () => ({ promise: promiseStubSqs })
    }
    lambda.__set__('sqs', sqsMock);
}

describe('handler', function () {
    beforeEach(() => {
        sinonSandbox = sinon.createSandbox();
    });

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

    describe('when SQS message is in dedupe cache', function () {
        beforeEach(() => {
            // mock SQS
            mockGoodSqsMove();
            // mock DynamoDBClient
            const promiseStub = sinonSandbox.stub().resolves({'Item': 'something'});
            sinonSandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'get').returns({ promise: promiseStub });
        });

        it('should return an error for a duplicate message', function () {
            return LamdbaTester(lambda.handler)
                .event(event.valid)
                .expectReject((err, additional) => {
                    expect(err).to.have.property('message', 'Duplicate message: {"Item":"something"}');
                });
        });
    });
});

答案 2 :(得分:0)

看看LocalStack。它提供了一个易于使用的测试/模拟框架,用于通过在本地计算机或Docker中启动与AWS兼容的API来开发与AWS相关的应用程序。它支持两种AWS API,其中包括SQS。确实是功能测试的绝佳工具,无需为此在AWS中使用单独的环境。