5

I have a problem to stub a call to DynamoDB for API testing. I'm using serverless mocha and want to test my API from an end-to-end perspective. The project structure is not straightforward, but inside the API file itself, I have a separate call to different class file to actually work with DynamoDB functions. Let's assume it as a library. So, I cannot use aws-sdk-mock since requirements "The AWS Service needs to be initialised inside the function being tested in order for the SDK method to be mocked" is not my case. How I can test my API and to stub calls to DynamoDB? Now test is actually working, but it makes real call to database which I want to avoid:

const isStub = true;

const mochaPlugin = require('serverless-mocha-plugin');
const chaiExclude = require('chai-exclude');

const sinon = require('sinon');

mochaPlugin.chai.use(chaiExclude);

const expect = mochaPlugin.chai.expect;
const assert = mochaPlugin.chai.assert;

let createHandler = mochaPlugin.getWrapper('postStory', '/../../functions/create/create.js', 'handler');

const { constants } = require('core/index');

const localConstants = require('../utils/constants');

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

describe('create', () => {

    let dynamoSpy = sinon.spy();

    before((done) => {
        if (isStub) {
            AWSMock.mock('DynamoDB.DocumentClient', 'put', dynamoSpy);
        }
        done();
    });
    after((done) => {
        if (isStub) {
            assert.isTrue(dynamoSpy.calledOnce, 'should make at least one call to DynamoDB via AWS SDK');
            AWSMock.restore('DynamoDB.DocumentClient', 'put');
            sinon.reset();
        }
        done();
    });

    it('should pass object with correct values to save', function () {
        return createHandler.run(require('../events/create/create.json')).then((response) => {
            console.log(response);
            expect(response.statusCode).to.equal(201);
        });
    });
levo4ka
  • 2,248
  • 1
  • 19
  • 32

1 Answers1

6

I had the same issue, I resolved it by using sinon, please see how to stub you Dynamo function and then test whatever you want:

import {expect} from 'chai';
import * as AWS from 'aws-sdk';
import * as sinon from 'sinon';

let result = {
  // your result
}
let sinonSandbox;

beforeEach((done) => {
    sinonSandbox = sinon.createSandbox();
    done();
})

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

it('your test', async () => {
    sinonSandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'put').returns({
        promise: function () {
            return Promise.resolve(result);
        }
    });

    return createHandler.run(require('../events/create/create.json')).then((response) => {
        console.log(response);
        expect(response.statusCode).to.equal(201);
    });
});

in this example, I stub the promise implementation I believe you can stub the put with a callback like this:

sinonSandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'put').returns((params,callback) => {
    callback(null,result);
});
Shay Moshe
  • 482
  • 4
  • 16
  • Thanks! Very weird, `sinonSandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'put').returns({promise: () => {}});` didn't work although it's almost the same and it would work for `query`... – Stéphane Bruckert Jan 10 '20 at 15:03