Question:
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
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); }); }); |
Answer:
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
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:
1 2 3 4 |
sinonSandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'put').returns((params,callback) => { callback(null,result); }); |