xamples
epeat
ode
pproach
ptimize
est
Testing and assertion libraries include Jasmine, Mocha, Chai, Sinon, etc.
Many have a special feature called spies. Spies allow test specs to track how specific functions of interest are used:
Implement a 'spyOn' function which does the following:
function adder(n1, n2) { return n1 + n2; }
var adderSpy = spyOn( adder );
adderSpy.getCallCount(); // 0
adderSpy(2, 4); // returns 6
adderSpy.getCallCount(); // 1
adderSpy(3, 5); // returns 8
adderSpy.getCallCount(); // 2
adderSpy.wasCalledWith(2); // true
adderSpy.wasCalledWith(0); // false
adderSpy.returned(6); // true
adderSpy.returned(9); // false
Keep in mind:
function spyOn (func) {
// keep track of function call count,
// initialize arrays to store results & arguments
let [callCount, calledWith, returnVals] = [0, [], []];
// function to be returned
function spy (...args) {
// code will go here
};
// create required methods on spy
spy.getCallCount = function() {
return callCount;
};
spy.wasCalledWith = function (val) {
// search through returnedVals array for val
};
spy.returned = function (val) {
// search through calledWithVals array for val
};
return spy;
}
// Remember that function arguments are an array-like object?
// Turn arguments into an actual array
// Array.prototype.slice.call(arguments)
// Then we can use the resulting array to call .apply() on our function
function spy () {
let args = [].slice.call(arguments);
let returnVal = func.apply(this, args);
// more code to follow
}
// We can also do this without using the 'arguments' object
// by using ES6's 'rest' and 'spread' operators.
function spy (...args) { // rest operator
let returnVal = func(...args); // spread operator
// more code to follow
}
function spyOn (func) {
let [callCount, calledWith, returnVals] = [0, [], []];
function spy (...args) {
let returnVal = func(...args);
// store result of applying function
returnVals.push(returnVal);
// add arguments array values to called values array
calledWith = calledWith.concat(args);
// increment function call count by 1
callCount++;
// return the result of the function call
return returnVal;
};
spy.getCallCount;
spy.wasCalledWith;
spy.returned;
return spy;
};
// The 'indexOf' method of an Array returns '-1' if a value is not found
// We can use this to return a boolean value for the two search methods
spy.wasCalledWith = function (val) {
return calledWith.indexOf(val) > -1;
};
spy.returned = function (val) {
return returnVals.indexOf(val) > -1;
};
// We can also use ES7's 'includes' method
spy.wasCalledWith = function (val) {
return calledWith.includes(val);
};
spy.returned = function (val) {
return returnVals.includes(val);
};
function spyOn (func) {
let [callCount, calledWith, returnVals] = [0, [], []];
function spy (...args) {
let returnVal = func(...args);
returnVals.push(returnVal);
calledWith = calledWith.concat(args);
callCount++;
return returnVal;
}
spy.getCallCount = function () {
return callCount;
};
spy.wasCalledWith = function (val) {
return calledWith.includes(val);
};
spy.returned = function (val) {
return returnVals.includes(val);
};
return spy;
}