Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking using aws-sdk-mock's promise support with DocumentClient

I'm trying to write a unit test using aws-sdk-mock's promise support. I'm using DocumentClient.

My code looks like this:

const docClient = new AWS.DynamoDB.DocumentClient();

const getItemPromise = docClient.get(params).promise();
   return getItemPromise.then((data) => {
   console.log('Success');
   return data;
}).catch((err) => {
   console.log(err);
});

My mock and unit test looks like this:

const AWS = require('aws-sdk-mock');
AWS.Promise = Promise.Promise;

AWS.mock('DynamoDB.DocumentClient', 'get', function (params, callback)
{
   callback(null, { Item: { Key: 'test value } });
});

dynamoStore.getItems('tableName', 'idName', 'id').then((actualResponse) => {
  // assertions
  done();
});

Runnning my unit test, does not return my test value, it actually bypasses my mock, and calls calls dynamoDb directly. What am I doing wrong? How can I get my mock set up properly?

like image 585
JAck28 Avatar asked Feb 24 '17 16:02

JAck28


3 Answers

It's unclear from your code but aws-sdk-mock has this note

NB: The AWS Service needs to be initialised inside the function being tested in order for the SDK method to be mocked

so the following will not mock correctly

var AWS      = require('aws-sdk');
var sns      = AWS.SNS();
var dynamoDb = AWS.DynamoDB();

exports.handler = function(event, context) {
  // do something with the services e.g. sns.publish 
}

but this will

var AWS = require('aws-sdk');

exports.handler = function(event, context) {
  var sns      = AWS.SNS();
  var dynamoDb = AWS.DynamoDB();
  // do something with the services e.g. sns.publish 
}

see more here https://github.com/dwyl/aws-sdk-mock#how-usage

like image 126
wyu Avatar answered Sep 23 '22 14:09

wyu


It might be too late for an answer, but I had the same problem and I stumbled upon this question. After a few tries I found a solution that doesn't involve aws-sdk-mock but only plain Sinon, and I hope that sharing it would help someone else. Note that the DynamoDB client is create outside the lambda.

The lambda itself looks like this:

const dynamoDB = new DynamoDB.DocumentClient();

exports.get = async event => {
    const params = {
        TableName: 'Tasks',
        Key: {
            id: event.pathParameters.id
        }
    };

    const result = await dynamoDB.get(params).promise();
    if (result.Item) {
        return success(result.Item);
    } else {
        return failure({ error: 'Task not found.' });
    }
};

And the test for this lambda is:

const sandbox = sinon.createSandbox();

describe('Task', () => {

    beforeAll(() => {
        const result = { Item: { id: '1', name: 'Go to gym'}};
        sandbox.stub(DynamoDB.DocumentClient.prototype, 'get').returns({promise: () => result});
    });

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

    it('gets a task from the DB', async () => {
        // Act
        const response = await task.get(getStub);
        // Assert
        expect(response.statusCode).toEqual(200);
        expect(response.body).toMatchSnapshot();
    });
});

I like to use Sinon's sandbox to be able to stub a whole lot of different DynamoDB methods and clean up everything in a single restore().

like image 22
Alessandro Cappello Avatar answered Sep 21 '22 14:09

Alessandro Cappello


sinon and proxyquire can be used to mock the dynamodb client.

It supports both callback based and async/await based calls.

Refer this link for full details https://yottabrain.org/nodejs/nodejs-unit-test-dynamodb/

like image 43
yottabrain Avatar answered Sep 19 '22 14:09

yottabrain