Easily mock aws-sdk API methods to enable easier testing of applications which use the AWS SDK for JavaScript.
Under the hood, this stubs aws-sdk methods using sinon.js.
Mocks an AWS service method to return the specified test data or a function
- service (string): the name of the AWS service that the method belongs to e.g. EC2, Route53 etc.
- method (string): the service's method to be be mocked e.g. describeTags
- data (object): the test data that the mocked method should return or a function that is called
The parameter data
can be either fixed data, in which case the original callback will be called with that data, or it can be a function. If it is a function, then when the mocked service is called, your function will be called.
If it is a function, it will be passed all of the parameters passed to the original AWS SDK call, including the callback. You are expected to call the callback.
Example of fixed data:
var AWS = require('mock-aws');
var ec2 = new AWS.EC2();
AWS.mock('EC2', 'describeTags', [ 'one', 'two', 'three' ]);
ec2.describeTags({}, function(err, data) {
console.log(data); // data should equal [ 'one', 'two', 'three' ];
});
Example of function:
var AWS = require('mock-aws');
var ec2 = new AWS.EC2();
AWS.mock('EC2', 'describeTags', function(params,callback){
params = params || {};
if (params.special) {
callback(null,"special");
} else if (params.strange) {
callback(null,"weird");
} else {
callback("ERROR!");
}
});
ec2.describeTags({}, function(err, data) {
console.log(err); // err should equal "ERROR!"
console.log(data); // data should be undefined
});
ec2.describeTags({special: true}, function(err, data) {
console.log(err); // err should be null
console.log(data); // data should be "special"
});
ec2.describeTags({strange:true}, function(err, data) {
console.log(err); // err should be null
console.log(data); // data should be "weird"
});
Removes mocked service method to restore the original functionality
- service (string): the name of the AWS service that the method belongs to e.g. EC2, Route53 etc.
- method (string): the service's method to be be restored e.g. describeTags
var AWS = require('mock-aws');
// Mock some EC2 methods to return specified test data
AWS.mock('EC2', 'describeTags', [ 'one', 'two', 'three' ]);
var ec2 = new AWS.EC2();
// EC2 methods should return specified test data
ec2.describeTags({}, function(err, data) {
console.log(data); // data should equal [ 'one', 'two', 'three' ];
});
// Call restore with a service & method
AWS.restore('EC2', 'describeTags');
// describeTags method now returns real AWS data
ec2.describeTags({}, function(err, data) {
console.log(data); // data should equal real data from AWS
});
Removes ALL mocked methods for given service to restore the original functionality
- service: (string) the name of the AWS service to restore e.g. EC2, Route53 etc.
var AWS = require('mock-aws');
var ec2 = new AWS.EC2();
AWS.mock('EC2', 'describeTags', [ 'one', 'two', 'three' ]);
AWS.mock('EC2', 'describeVpcs', 'vpcs');
ec2.describeTags({}, function(err, data) {
console.log(data); // data should equal [ 'one', 'two', 'three' ];
});
ec2.describeVpcs({}, function(err, data) {
console.log(data); // data should equal 'vpcs';
});
AWS.restore('EC2');
ec2.describeTags({}, function(err, data) {
console.log(data); // data should be real data from AWS
});
ec2.describeVpcs({}, function(err, data) {
console.log(data); // data should be real data from AWS
});
Removes ALL mocked services & methods to restore the original functionality
var AWS = require('mock-aws');
var ec2 = new AWS.EC2();
var s3 = new AWS.S3();
AWS.mock('EC2', 'describeTags', [ 'one', 'two', 'three' ]);
AWS.mock('EC2', 'describeVpcs', 'vpcs');
AWS.mock('S3', 'listBuckets', { buckets: [] });
ec2.describeTags({}, function(err, data) {
console.log(data); // data should equal [ 'one', 'two', 'three' ];
});
ec2.describeVpcs({}, function(err, data) {
console.log(data); // data should equal 'vpcs';
});
s3.listBuckets({}, function(err, data) {
console.log(data); // data should equal { buckets: [] };
})
AWS.restore('EC2');
ec2.describeTags({}, function(err, data) {
console.log(data); // data should be real data from AWS
});
ec2.describeVpcs({}, function(err, data) {
console.log(data); // data should be real data from AWS
});
s3.listBuckets({}, function(err, data) {
console.log(data); // data should equal { buckets: [] };
})
I want to build and test a tag validator that returns the id's of any EBS volumes which don't have a tag called 'name'. My production code for my tag-validator may look something like the following:
var AWS = require('aws-sdk');
function getNamelessVolumes(region, callback) {
var ec2 = new AWS.EC2({ region: region });
ec2.describeVolumes({}, function(err, data) {
if (err) callback(err, null);
var namelessVolumes = [];
data.Volumes.forEach(function(volume) {
var named = false;
for (var i = 0; i < volume.Tags.length; i++) {
if (volume.Tags[i].Key.toLowerCase() === 'name') {
named = true;
break;
}
}
if (!named) {
namelessVolumes.push(volume.VolumeId);
}
});
callback(null, namelessVolumes);
});
}
module.exports = {
getNamelessVolumes: getNamelessVolumes
};
In order to test my validator, I don't want to actually call AWS, nor do I want to have to change my production code. The mock-aws module solves this problem - I can easily mock the describeVolumes method in my test then call the tag validator as normal. This way I can use varying test data to fully test the getNamelessVolumes function, without relying on AWS services. First I setup my test data:
{
"Volumes": [
{
"VolumeId": "v-111",
"Tags": [
{
"Key": "name",
"Value": "volume 1"
},
{
"Key": "role",
"Value": "test"
}
]
},
{
"VolumeId": "v-222",
"Tags": [
{
"Key": "role",
"Value": "test"
}
]
}
]
}
Now I can write my test, mocking describeVolumes() to return my test data
var should = require('should');
var AWS = require('mock-aws'); // include mock-aws instead of aws-sdk
var tagValidator = require('../lib/tag-validator');
describe('tag-validator', function() {
describe('getNamelessVolumes()', function() {
it('should return the ids of volumes which do NOT contain a "name" tag', function(done) {
// Test data for the AWS method to return
var testData = require('./test-data.json');
// Mock the aws-sdk method 'describeVolumes' to return the test data
AWS.mock('EC2', 'describeVolumes', testData);
// Call the function I'm trying to test
tagValidator.getNamelessVolumes('us-east-1', function(err, data) {
// Assert that getNamelessVolumes() returned the correct results
data.length.should.eql(1);
data[0].should.eql('v-222');
done();
});
});
});
});
The point here is that I can test the functionality of my tag-validator without making real calls to AWS and I never had to modify my production code in order to make it testable. mock-aws handled it for me.
I built this for myself but feel free to use, share, submit bugs / pull requests, suggest changes or features etc.