I have a simple AWS Node.js Lambda, which I would like to test using mocks:
//SimpleLambda.js
var AWS = require('aws-sdk');
exports.handler = function(event, context) {
var name = getName();
context.succeed(name);
};
function getName() {
return 'David';
}
I've installed mocha and simple-mock, but I am unable to get this to work:
//test.js
//Mocha
var assert = require('assert');
//Chai
var chai = require('chai');
var expect = chai.expect;
var should = chai.should();
//Simple-Mock
var simple = require('simple-mock');
//Lambda
var lambda = require('../SimpleLambda');
describe('SimpleLambda tests', function() {
describe('Get name', function() {
beforeEach(function() {
simple.mock(lambda, 'getName');
});
it('should return \'Tim\' when the mocked with simple-mock', function() {
lambda.getName.returnWith('Tim');
var context = {
invokeid: 'invokeid',
succeed: function(result) {
expect(result).to.equal("Tim");
return result;
}
};
lambda.handler({}, context);
});
});
});
Output still suggests getName returns 'David'
SimpleLambda tests
Get name
1) should return 'Tim' when the mocked with simple-mock
0 passing (11ms)
1 failing
1) SimpleLambda tests Get name should return 'Tim' when the mocked with simple-mock:
AssertionError: expected 'Succesfully retrieved: David' to equal 'Tim'
+ expected - actual
-Succesfully retrieved: David
+Tim
at Object.context.succeed (test/test.js:27:29)
at Object.exports.handler (SimpleLambda.js:5:11)
at Context.<anonymous> (test/test.js:32:14)
Can this be done?
You need to export your getName function so that it's accessible from test.js (and can be wrapped by your mocking library).
Something like this:
//SimpleLambda.js
var AWS = require('aws-sdk');
exports.handler = function(event, context) {
var name = exports.getName();
context.succeed(name);
};
exports.getName = function (){
return 'David';
}
Try to put simple.mock(lambda, 'getName').returnWith('Tim'); to beforeEach and delete this lambda.getName.returnWith('Tim');.
Related
Trying to write a unittest for the below module in /utility/sqsThing.js. However I'm having diffuculty mocking the sqs.sendMessage method. Anyone know how I should go about this. I'm using the sinon library, and mocha for running the tests.
The function that I'm trying to unittest utility/sqsThing.js:
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const outputQueURL = 'https:awsUrl';
const SQSOutputSender = (results) => {
const params = {
MessageBody: JSON.stringify(results),
QueueUrl: outputQueURL,
};
// Method that I want to mock
sqs.sendMessage(params, function (err, data) {
if (err) {
console.log('Error');
} else {
console.log('Success', data.MessageId);
}
});
};
My attempt at mocking the sqs.sendMessage method in a unittest sqsThingTest.js:
const sqsOutputResultSender = require('../utility/sqsThing');
const AWS = require('aws-sdk');
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('SQS thing test', function() {
beforeEach(function () {
sinon.stub(sqs, 'sendMessage').callsFake( function() { return 'test' });
});
afterEach(function () {
sqs.sendMessage.restore();
});
it('sqsOutputResultSender.SQSOutputSender', function() {
// Where the mock substitution should occur
const a = sqsOutputResultSender.SQSOutputSender('a');
expect(a).toEqual('test');
})
});
Running this unittest with mocha tests/unit/sqsThingTest.js however I get:
AssertionError: expected undefined to deeply equal 'test'.
info: Error AccessDenied: Access to the resource https://sqs.us-east-1.amazonaws.com/ is denied..
It looks like the mock did not replace the aws api call. Anyone know how I can mock sqs.SendMessage in my test?
You could use rewire js it is a library that lets you inject mocked properties into your module you want to test.
Your require statement would look something like this:
var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');
Rewire will allow you to mock everything in the top-level scope of you sqsThing.js file.
Also you need to return the value of sqs.sendMessage this will remove the issue expected undefined to deeply equal 'test'
Your original file would look the same just with a return statement.
//utility/sqsThing.js
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const outputQueURL = 'https:awsUrl';
const SQSOutputSender = (results) => {
const params = {
MessageBody: JSON.stringify(results),
QueueUrl: outputQueURL,
};
// Method that I want to mock
return sqs.sendMessage(params, function (err, data) {
if (err) {
console.log('Error');
} else {
console.log('Success', data.MessageId);
}
});
};
You would then write your unit test as follows:
//sqsThingTest.js
var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('SQS thing test', function() {
beforeEach(function () {
sqsOutputResultSender.__set__("sqs", {
sendMessage: function() { return 'test' }
});
});
it('sqsOutputResultSender.SQSOutputSender', function() {
// Where the mock substitution should occur
const a = sqsOutputResultSender.SQSOutputSender('a');
expect(a).toEqual('test');
})
});
This example returns an object with a property of sendMessage but this could be replaces with a spy.
Rewire Docs
Try moving the declaration of sqsOutputResultSender after you have stubbed the sendmessage function
var sqsOutputResultSender;
const AWS = require('aws-sdk');
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('SQS thing test', function() {
beforeEach(function () {
sinon.stub(sqs, 'sendMessage').callsFake( function() { return 'test' });
sqsOutputResultSender = require('../utility/sqsThing');
});
afterEach(function () {
sqs.sendMessage.restore();
});
it('sqsOutputResultSender.SQSOutputSender', function() {
// Where the mock substitution should occur
const a = sqsOutputResultSender.SQSOutputSender('a');
expect(a).toEqual('test');
})
});
I wrting API test in Mocha JS, have two files: 00_auth.js and utils.js
I want to create function in utils which is available in other files from same folder
utils.js
utils = {
randomStringGenerator: function (){
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 7);
}
};
and test js
const chai = require('chai');
const mocha = require('mocha');
const config = require('../config');
const request = require('supertest')(url);
const assert = chai.assert;
const utils= require('./utils')
randomFirstName=utils.randomStringGenerator();
//randomLastName=stringGenerator();
randomMail=randomFirstName+'#'+randomLastName+'.pl';
auth_token = ''
describe('0_auth', () => {
it('should return token for unauthorized user', function(done) {
request
.post('/rest/v1/auth/get-token')
.set(config.headers)
.send({
"deviceUuidSource": "DEVICE",
"source" : "KIOSK",
"deviceUuid" : "uniquedeviceuuid"
})
.end(function(err,res){
assert.equal(res.status,200)
assert.property(res.body, 'token')
assert.isString(res.body.token)
auth_token=res.body.token
console.log('unathorized token: '+auth_token)
done(err);
});
});
});
I took this solution from Global functions in javascript, but it's not working, gives me Type Error :utils.randomStringGenerator is not a function
OK, got it, thanks
module.exports.randomStringGenerator = function (){
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 7);
}
I am using Swagger Node with express and I initialized the skeleton project. Swagger project create hello-world
Then inside the hello-world/api/controllers/hello_world.js I added a small modification to require a helper hello_helper.js and call its function helloHelper.getName().
'use strict';
let helloHelper = require('../helpers/hello_helper');
var util = require('util');
module.exports = {
hello: hello
};
function hello(req, res) {
var name = req.swagger.params.name.value || helloHelper.getName();
var hello = util.format('Hello, %s!', name);
res.json(hello);
}
hello-world/api/helpers/hello_helper.js
'use strict';
module.exports = {getName: getName};
function getName() {
return 'Ted';
}
I would like to stub helloHelper.getName() to return 'Bob' instead.
I can do so easily with:
hello-world/test/api/controllers/hello_world.js
// Create stub import of hello_helper
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', { '../helpers/hello_helper': { getName: function () { return 'Bob'; } }
});
Using supertest how can I make swagger recognize my stub?
EDIT: Thanks to help from the answer below this solution worked for me.
var app, getNameStub, mockHelloHelper, request;
beforeEach(function (done) {
// Create stub import of hello_helper
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', {
'../helpers/hello_helper': {
getName: function () {
return 'Bob';
}
}
});
app = require('../../../app');
request = supertest(app);
done();
});
...
it('should return a default string', function(done) {
request
.get('/hello')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.eql('Hello, Bob!');
done();
});
});
You need to initialize/require express app after you have proxyquired your dependency. Only then it can use your stubbed version of getName:
beforeEach(function () {
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', {
'../helpers/hello_helper': {
getName: function () {
return 'Bob';
}
}
});
// initialize/require your app here
request = supertest(app);
});
I have this code:
var async = require('async'),
util = require('util');
var Parse = require('parse/node');
function signup(userInfo, callback) {
var username = userInfo.username,
email = userInfo.email,
password = userInfo.password;
var user = new Parse.User();
user.set('username', username);
user.set('email', email);
user.set('password', password);
user.signUp(null, {
success: (user) => {
// console.log('BaaS Signup success ' + util.inspect(user));
callback(null, user);
},
error: (user, error) => {
// console.log('BaaS Signup error ' + util.inspect(error));
callback(JSON.stringify(error));
}
});
}
I want to unit test it, and as such need to be able to test the content of the success and error function.
If user was a library, I could use proxyquire and put a stub returning a promise and be done with it, however, user is constructed.
How can I stub Parse.User() so that I can control the resulting object?
This seems to work:
// test `success` callback
let testUser = { user : 'test' };
let stub = sinon.stub(Parse.User.prototype, 'signUp')
.yieldsTo('success', testUser);
You should be able to stub the constructor just like you'd stub any other funtion, and just return your fake object:
sinon.stub(Parse, "User")
.andReturn(fakeUser);
let u = new Parse.User();
//u === fakeUser
While it is ugly as hell, I ve succeed in making my test work with this:
var chai = require('chai'),
expect = chai.expect,
util = require('util');
var proxyquire = require('proxyquire').noPreserveCache();
var sinon = require('sinon');
describe('SignUp', () => {
it('Expect to sign up the user and return the user', (done) => {
var stub = {
parse: {
User: function User() {
this.set = () => {};
this.signUp = (a, c) => {
c.success({id: 'UserID'});
};
}
}
},
baas = proxyquire('./../baas.js', {
'parse/node': stub.parse
});
baas.signup({
username: 'User',
email: 'user#test.com',
password: 'Password'
}, (err, user) => {
try {
expect(err).to.not.be.ok;
expect(user).to.be.ok;
done();
} catch(err) {
done(err);
}
});
});
});
The answer I received made me realize I don't use sinon like I should, and all my test are built by hacking around part of proxyquire and sinon together.
I will need to reread the documentation.
I am having issues writing unit test for the following setup as a jira.js file (in a node.js module):
var rest = require('restler'); // https://www.npmjs.com/package/restler
module.exports = function (conf) {
var exported = {};
exported.getIssue = function (issueId, done) {
...
rest.get(uri).on('complete', function(data, response) {
...
};
return exported;
};
Now, i want to write unit test for my getIssue function. 'restler' is a REST client through which i make REST calls to the JIRA API to get a JIRA issue via my code.
So to be able to test createIssue(..), I want to be able to mock the 'rest' var in my Jasmine unit tests.
How can i mock this method? Please give me some pointers so that i can go ahead. I have tried using rewire but i have failed.
This is what i have so far which does not work (ie. getIssue method turns out to be undefined):
var rewire = require("rewire");
var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
var cfg = require("../../../config.js").Configuration;
var jiraModule = rewire("../lib/jira")(cfg);
var sinon = require("sinon");
var should = require("should");
// https://github.com/danwrong/restler
var restMock = {
init : function () {
console.log('mock initiated'+JSON.stringify(this));
},
postJson : function (url, data, options) {
console.log('[restler] POST url='+url+', data= '+JSON.stringify(data)+
'options='+JSON.stringify(options));
emitter.once('name_of_event',function(data){
console.log('EVent received!'+data);
});
emitter.emit('name_of_event', "test");
emitter.emit('name_of_event');
emitter.emit('name_of_event');
},
get : function (url, options) {
console.log('[restler] GET url='+url+'options='+JSON.stringify(options));
},
del : function (url, options) {
console.log('[restler] DELETE url='+url+'options='+JSON.stringify(options));
},
putJson : function (url, data, options) {
console.log('[restler] PUT url='+url+', data= '+JSON.stringify(data)+
'options='+JSON.stringify(options));
}
};
var cfgMock = {
"test" : "testing"
};
jiraModule.__set__("rest", restMock);
jiraModule.__set__("cfg", cfgMock);
console.log('mod='+JSON.stringify(jiraModule.__get__("rest")));
describe("A suite", function() {
it("contains spec with an expectation", function() {
restMock.init();
restMock.postJson(null, null, null);
console.log(cfg.jira);
// the following method turns out to be undefined but when i console.log out the jiraModule, i see the entire code outputted from that file
jiraModule.getIssue("SRMAPP-130", function (err, result) {
console.log('data= '+JSON.stringify(result));
});
expect(true).toBe(true);
});
});
If someone can guide me on how to mock the 'rest' require dependency & unit test this method that will be very helpful.
Also, how should i mock the 'conf' being passed to module.exports?
thanks
You could use proxyquire or mockery to stub/mock the dependencies.
In the below example I have used proxyquire. Hope it helps.
/* ./src/index.js */
var rest = require('restler');
module.exports = function (conf) {
var exported = {};
exported.getIssue = function (issueId, done) {
var uri = '';
var reqObj = '';
var service = {
auth : ''
};
rest.postJson(uri, reqObj, service.auth).on('complete', function(data, response) {
done(data, response);
});
};
return exported;
};
/* ./test/index.js */
var proxyquire = require('proxyquire');
var assert = require('chai').assert;
var restlerStub = {
postJson: function() {
return {
on: function(event, callback) {
callback('data', 'response');
}
}
}
}
var index = proxyquire('../src/index', {'restler': restlerStub})();
describe('index', function() {
it('should return the desired issue', function(done) {
var issue = index.getIssue('issueId', function(data, response) {
assert.equal(data, 'data');
assert.equal(response, 'response');
done();
})
});
});
/* ./package.json */
{
"scripts": {
"test": "mocha"
},
"dependencies": {
"restler": "^3.4.0"
},
"devDependencies": {
"chai": "^3.4.1",
"mocha": "^2.3.4",
"proxyquire": "^1.7.3"
}
}