Proxyquire does not stub - javascript

I'm trying to use proxyquire to stub the spawnSync method of the child_process module, but it doesn't work. The console.log(gitResponse) in my index.js file doesn't return the stubbed string, but the unstubbed response (in this case, the git help text).
Can someone see what I am doing wrong?
/index.js
var childProcess = require('child_process');
function init () {
var gitInit = childProcess.spawnSync('git', ['init']);
var gitResponse = gitInit.stdout.toString() || gitInit.stderr.toString();
console.log(gitResponse);
}
module.exports = {
init: init
}
/test/indexTest.js
var assert = require('assert');
var index = require('../index.js');
var sinon = require('sinon');
var proxyquire = require('proxyquire');
describe('test', function () {
it('tests', function () {
var spawnSyncStub = function (command, args) {
return {
stdout: {
toString: () => "git init success string"
}
};
};
proxyquire('../index.js', {
'child_process': {
spawnSync: spawnSyncStub
}
});
index.init();
}
}

According to the documentation; should you not be doing something like this:?
var assert = require('assert');
var index = proxyquire('../index.js', {
'child_process': {
spawnSync: function (command, args) {
return {
stdout: {
toString: () => "git init success string"
}
};
}
}
});
var sinon = require('sinon');
var proxyquire = require('proxyquire');
describe('test', function () {
it(
'tests'
,function () {
sinon.assert.match(index.init(), "git init success string");
}
)
});

Related

How to mock a function in another function nodejs

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');
})
});

Test plain javascript file returning different objects

Is it possible to test the code below with Jasmine testing tool or any other npm module like rewire or similar?
const AuthValidatorDumb = require('./src/AuthValidatorDumb');
const AuthValidator = require('./src/AuthValidator');
const config = require('../config');
let instance;
if (!instance) {
if (config.get('auth.enabled')) {
instance = AuthValidator;
} else {
instance = AuthValidatorDumb;
}
}
module.exports = instance;
I've got a variant for testing the code above.Suppose you have:
1) The code for index.js in the question above.
2) AuthValidator.js:
class AuthValidator {}
module.exports = AuthValidator;
3) AuthValidatorDumb.js:
class AuthValidatorDumb {}
module.exports = AuthValidatorDumb;
Here is test/index.spec.js:
const proxyquire = require('proxyquire');
const AuthValidator = require('../src/AuthValidator');
const AuthValidatorDumb = require('../src/AuthValidatorDumb');
describe('auth index', () => {
it('should return AuthValidator', () => {
const configMock = { get: () => 'sth' };
const Instance = proxyquire('../index', {
'../config': configMock,
});
expect(new Instance() instanceof AuthValidator).toBeTruthy();
});
it('should return AuthValidatorDumb', () => {
const configMock = { get: () => undefined };
const Instance = proxyquire('../index', {
'../config': configMock,
});
expect(new Instance() instanceof AuthValidatorDumb).toBeTruthy();
});
});

node.js proxyquire stub asynchronous function from module required by another module

Module under test:
'use strict';
const config = require('config');
const q = require('q');
class RedisAccess {
static getValue(key) {
let deferred = q.defer();
if (config.redis.disableInteraction) {
deferred.resolve();
return deferred.promise;
}
config.redisClient.get(key, function handleResults(err, result) {
...
return deferred.promise;
}
}
exports = module.exports = RedisAccess;
Test:
var proxyquire = require('proxyquire').noPreserveCache();
var assert = require('assert');
var readdirError = new Error('some error');
var redisClientStub = { };
var calledBack;
// Override redisClient used by RedisAccess.js.
var redisClientProxy = proxyquire('../../../lib/data/redis/RedisAccess.js', { 'config' : redisClientStub });
// Test redisClient.get(...) to retrieve value given key using proxyquire for redisClient.
redisClientStub.redisClient.get = function (key, cb) {
cb(null, 'hello world');
};
calledBack = false;
// Test redisClient getValue async function.
redisClientProxy.getValue('some_key', function (err, value) {
assert.equal(err, null);
assert.equal('value', 'hello world');
callback = true;
});
The error when I execute the test is:
redisClientStub.redisClient.get = function (key, cb) {
^
TypeError: Cannot set property 'get' of undefined
How do I properly stub the config.redisClient.get(...) function?
I figured this out. I had to put a "stub within a stub" to stub the config.redisClient.get() function:
// Proxyquire allows unobstrusively overriding dependencies during testing.
// Override config used by RedisAccess.js.
var configStub = {
redisClient : {
createClient : function (port, address) {
// redis-mock-js used instead.
},
get : function (key, cb) {
if(key === 'test-rejected') {
cb(new Error('test-rejected'), 'rejected-promise');
}
else if(key === 'test-true') {
cb(null, true);
}
else if(key === 'test-get-valid') {
cb(null, 'valid-value');
}
else {
cb(new Error('Should not have gotten here!'), 'value');
}
},
}
};
which allowed me to construct this proxyquire:
var redisAccessProxy = proxyquire('lib/data/redis/RedisAccess.js', { 'config' : configStub });
and run this test using a proxy function for redisClient.get(...) which is called inside of RedisAccess.getValue(...):
var val = redisAccessProxy.getValue('test-get-valid');
assert.equal(val.isFulfilled(), true);
assert.equal(val.isRejected(), false);
assert.equal(val, 'valid-value');

Mocking in AWS Lambda

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');.

node js unit testing: mocking require dependency

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"
}
}

Categories