Stubbing and verification for node.js tests. Enables you to validate and override behaviour of nested pieces of code such as methods, require() and npm modules or even instances of classes.
This library is inspired on node-gently, MockJS and mock-require.
##API
var using = require('using')(); //an instance of using
using(object)('method').expect([countMatch], object.method([paramMatchers...]), [stubFn]);
var foo = {
bar: function(callback){
callback("bar!!");
}
}
using(foo)('bar').expect(
1,
foo.bar(using.aFunction),
function(c){
c("mock foo.bar()");
}
);
foo.bar(function(response){
console.log(response); //logs "mock foo.bar()"
});
####restore methods using(object)('method').restore();
using(foo)('bar').restore();
####restore objects (all methods) using(object).restore();
using(foo).restore();
var module = using.require(moduleName);
Note: module is still executed normally when requested, if you'd rather the module not to be executed at all, see entire module stubbing.
var uProcess = using.require('child_process');
using(uProcess)('exec').expect(
using.atLeast(1),
uProcess.exec(using.aString, using.anObject, using.aFunction),
function(s,o,c){
c();
}
);
require
####restore module methods
uProcess('exec').restore();
using.require.stub(moduleName, mockModule);
Stub entire module and avoid the module to be executed at all.
using.require.stub('module', {}); //replace module with this empty object
Of course, we can still verify/stub specific methods in our stubbed object.
var module = using.require('module');
using(module)('foo').expect(module.foo(/*...*/), /*...*/);
####restore normal module using.require.restore(moduleName);
using.require.restore('module');
var instance = using(ClassModule).instance([countMatch], new ClassModule([paramMatchers...]), [stubInstance]);
Note: This only works for classes wrapped within require() modules.
Consider the following module ./Cat.js :
function Cat(name){
this.name = name;
}
Cat.prototype = {
pet: function(){
return this.name +" "+ randomBehaviour();
}
}
module.exports = Cat;
Within our tests, we can stub/verify behaviour on specific class instances via:
var Cat = using.require('./Cat');
//be it cat an instance of new Cat(using.aString)
var cat = using(Cat).instance(new Cat(using.aString));
//example - stub cat.pet()
using(cat)('pet').expect(
cat.pet(),
function(){
return this.name + " purrs.";
}
);
using.verify([msg]);
using.verify("Something went wrong!");
using.restore();
using.restore();
using(object)('method').fail();
Expects this method never to be called.
Simplified alias of expecting 0 times matching everything:
using(object)('method').fail();
//simplified alias for:
using(foo)('bar').expect(0, foo.bar(using.everything));
###matchers
The simplest way to exactly match a parameter is by specifying it directly.
using(foo)('bar').expect(1, foo.bar(5));
//
foo.bar(5); //matches
foo.bar("5"); //does not match
Or, you can use any callback as a matcher (returning true matches)
var matchFrom1to5 = function(param){
return typeof(param)==='number' && param > 0 && param <5; // number from 1 to 5
}
using(foo)('bar').expect(2, foo.bar(matchFrom1to5));
//
foo.bar(3); //matches
foo.bar(6); //does not match
using-stubs provides you a few common matchers for easy use
using.aString //matches any string
using.aStringLike(regex) //matches the regular expression
using.anInt //matches any integer
using.aNumber //matches any number
using.anObject //matches any object (not null)
using.aFunction //matches any function
using.typeOf(type) //tests typeOf(parameter)===type
using.instanceOf(Class) //tests instanceOf(parameter)===Class
using.something //matches !==undefined
using.anything //matches any param as long as it is set (even undefined)
using.anObjectLike(obj, [boolean strict]) //deep compare to given object
//strict - defaults to non-strict (==) comparison (false)
using.everything //special matcher - all arguments from this point onward will be matched, even if none is set
//eg. foo("a", Match.everything) will match foo("a"), foo("a", "one"), foo("a", 1, 2, 3, 4, 5, 6);
You can specify an exact match directly
using(foo)('bar').expect(5, foo.bar()); //expects 5 executions
Or use a callback matcher
var matchFrom1to5 = function(param){
return typeof(param)==='number' && param > 0 && param <5; // number from 1 to 5
}
using(foo)('bar').expect(matchFrom1to5, foo.bar()); //expects 1 to 5 executions
using-stubs provides you a few common matchers for easy use
using.atLeast(x) //executed at least x times
using.atMost(x) //executed at most x times
using.between(x, y) //executed between x and y times