I am trying to write some test coverage for an app that uses the aws-sdk
NPM module that pushes things up to a SQS queue, but I am unsure how to mock things correctly.
Here is my test so far:
var request = require('superagent'),
expect = require('chai').expect,
assert = require('chai').assert,
sinon = require('sinon'),
AWS = require('aws-sdk'),
app = require("../../../../app");
describe("Activities", function () {
describe("POST /activities", function () {
beforeEach(function(done) {
sinon.stub(AWS.SQS.prototype, 'sendMessage');
done();
});
afterEach(function(done) {
AWS.SQS.prototype.sendMessage.restore();
done();
});
it("should call SQS successfully", function (done) {
var body = {
"custom_activity_node_id" : "1562",
"campaign_id" : "318"
};
reqest
.post('/v1/user/123/custom_activity')
.send(body)
.set('Content-Type', 'application/json')
.end(function(err, res) {
expect(res.status).to.equal(200)
assert(AWS.SQS.sendMessage.calledOnce);
assert(AWS.SQS.sendMessage.calledWith(body));
});
});
});
});
The error I am seeing is:
1) Activities POST /activities "before each" hook:
TypeError: Attempted to wrap undefined property sendMessage as function
2) Activities POST /activities "after each" hook:
TypeError: Cannot call method 'restore' of undefined
I am a bit of a newb when it comes to sinon.stub
or mocking objects in JavaScript, so please excuse my ignorance
AWSome mocks for Javascript aws-sdk services. This module was created to help test AWS Lambda functions but can be used in any situation where the AWS SDK needs to be mocked. If you are new to Amazon WebServices Lambda (or need a refresher), please checkout our our.
The sinon. stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.
JS. Sandboxes removes the need to keep track of every fake created, which greatly simplifies cleanup. var sandbox = require("sinon").
Sinon spies are used to record information about function calls. Unlike mocks or stubs, spies do not replace the function being called. Spies just record what parameters the function was called with, what value it returned, and other information about the function execution.
This is how I stub the AWS-SDK using sinonjs
import AWS from 'aws-sdk'
import sinon from 'sinon'
let sinonSandbox
const beforeEach = (done) => {
sinonSandbox = sinon.sandbox.create()
done()
}
const afterEach = done => {
sinonSandbox.restore()
done()
}
lab.test('test name', (done) => {
sinonSandbox.stub(AWS, 'SQS')
.returns({
getQueueUrl: () => {
return {
QueueUrl: 'https://www.sample.com'
}
}
})
done()
})
Basically I control all the methods from the main SQS. Hope this will help someone
We have created an aws-sdk-mock npm module which mocks out all the AWS SDK services and methods. https://github.com/dwyl/aws-sdk-mock
It's really easy to use. Just call AWS.mock with the service, method and a stub function.
AWS.mock('SQS', 'sendMessage', function(params, callback) {
callback(null, 'success');
});
Then restore the methods after your tests by calling:
AWS.restore('SQS', 'sendMessage');
I think the issue is that AWS SDK classes are built dynamically from JSON configuration. Here's the one for SQS: Github.
All API calls eventually make it down to makeRequest
or makeUnauthenticatedRequest
on Service, so I just stubbed those using withArgs(...)
. For example:
var stub = sinon.stub(AWS.Service.prototype, 'makeRequest');
stub.withArgs('assumeRole', sinon.match.any, sinon.match.any)
.yields(null, fakeCredentials);
which worked fine for my simple use case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With