Last active
August 29, 2015 14:10
-
-
Save indieisaconcept/21261cd9c7ff04be4447 to your computer and use it in GitHub Desktop.
Mocking node.js dependies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var proxyquire = require('proxyquire').noPreserveCache(), | |
leche = require('leche'), | |
sinon = require('sinon'), | |
npath = require('path'), | |
_ = require('lodash'); | |
/** | |
* @ngdoc function | |
* @name proxy | |
* | |
* @description | |
* Creates a scoped function using passed in base path which permits the loading | |
* of a module mocking / faking it's required dependencies via proxyquire | |
* | |
* @param {string} base Base path to use for when loading modules | |
* | |
* @returns {function} | |
* | |
*/ | |
module.exports = function proxy (base) { | |
base = base || module.parent && | |
npath.dirname(module.parent.id) || __dirname; | |
/** | |
* @ngdoc function | |
* @name load | |
* | |
* @description | |
* Enhanced wrapper around proxyquire permitting mocks to be generated, using | |
* leche. | |
* | |
* @param {string} subject The module path to load | |
* @param {object} mocks Object describing the mocks to be applied | |
* | |
* @example | |
* | |
* subject = prxy('../../../../lib/template-loader/', { | |
* 'logging' : { | |
* require: '../logging', | |
* using: { | |
* type: 'fake', | |
* src: '../../../../lib/logging' | |
* } | |
* } | |
* }; | |
* | |
* @returns {function} | |
* | |
*/ | |
return function load (subject, mocks) { | |
mocks = mocks || {}; | |
var locals = {}; | |
subject = npath.resolve(base, subject); | |
// create mocks for use when proxying | |
if (mocks) { | |
locals = Object.keys(mocks).reduce(function (acc, next) { | |
if (next === 'sandbox') { | |
console.log(next); | |
} | |
var item = mocks[next], | |
mock = item.using && item.using.type || 'fake', | |
src = item.using && item.using.src, | |
handler, | |
rtn; | |
src = _.isString(src) ? npath.resolve(base, src) : src; | |
rtn = module.exports.create(next, mock, src); | |
delete module.exports.require.cache[module.exports.require.resolve(src)]; | |
if (rtn) { | |
acc.proxy[item.require] = rtn; | |
acc.mocks[next] = rtn; | |
} | |
return acc; | |
}, { | |
proxy: {}, | |
mocks: {} | |
}); | |
locals = { | |
module : module.exports.proxyquire(subject, locals.proxy), | |
mocks : locals.mocks | |
}; | |
} | |
return locals; | |
}; | |
}; | |
/** | |
* @ngdoc function | |
* @name helpers | |
* | |
* @description | |
* Mock helpers | |
* | |
*/ | |
module.exports.helpers = { | |
'fake' : leche.fake, | |
'create': function (src) { | |
var result; | |
result = _.isString(src) ? module.exports.require(src) : src; | |
result = _.isPlainObject(result) ? Object.keys(result) : result; | |
result = _.isFunction(result) ? | |
result : (_.isArray(result) ? leche.create(result) : null); | |
return result; | |
}, | |
'stub' : sinon.stub, | |
'spy' : sinon.spy, | |
'mock' : sinon.mock | |
}; | |
module.exports.proxyquire = proxyquire; | |
module.exports.require = require; | |
/** | |
* @ngdoc function | |
* @name creates | |
* | |
* @description | |
* Creates mocks using pre-defined mock helpers | |
* | |
* @param {string} name The mock name | |
* @param {string} method The type of mock to use | |
* @param {string|funciton} src The src for the mock | |
* | |
* @example | |
* | |
* create('sandbox', 'stub', '../../path/to/module'); | |
* create('sandbox', 'stub', function () {}); | |
* | |
* @returns {object|function} mock | |
* | |
*/ | |
module.exports.create = function (name, method, src) { | |
var result = _.isString(src) ? module.exports.require(src) : src, | |
handler = module.exports.helpers[method]; | |
if (!handler) { | |
throw new Error('Unknown mock type used: ' + method); | |
} | |
result = _.isFunction(result) ? function () { | |
throw new Error('Unexpected call to "' + name + '"'); | |
} : handler(result); | |
return result; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Using a combination of the following modules behind the scenes.
Example
Known limitations