jsmock
Advanced tools
Comparing version 0.4.0 to 0.5.0
const matcher = require('./lib/matcher'); | ||
const Mock = require('./lib/mock'); | ||
const mock = require('./lib/mock'); | ||
module.exports = { | ||
_: matcher.any, | ||
Mock: Mock | ||
Mock: mock.Mock, | ||
UnexpectedCall: mock.UnexpectedCall | ||
} |
'use strict'; | ||
const _ = require('lodash'); | ||
const check = require('./check'); | ||
@@ -13,4 +14,3 @@ // Default action - dummy function | ||
/** @constructor | ||
* | ||
* @param {Expectation} owner | ||
* | ||
* @param {Any} action | ||
@@ -30,4 +30,3 @@ * If provided action is a function it will be executed with arguments provided to | ||
*/ | ||
constructor(owner, action, counter) { | ||
this.owner = owner; | ||
constructor(action, counter) { | ||
if(typeof action !== 'function') { | ||
@@ -47,9 +46,5 @@ this.action = () => action; | ||
setCounter(counter) { | ||
if(typeof counter !== 'number') { | ||
throw new TypeError('Action counter should be a valid number'); | ||
} | ||
check.type(counter, 'number', 'Action counter should be a valid number'); | ||
this.counter = parseInt(counter); | ||
if(this.counter === 0) { | ||
throw new Error('Can\'t create action with 0 expected execution times'); | ||
} | ||
check.assert(this.counter !== 0, 'Can\'t create action with 0 expected execution times'); | ||
} | ||
@@ -70,3 +65,3 @@ | ||
*/ | ||
ready() { | ||
available() { | ||
return this.counter != 0; | ||
@@ -84,25 +79,8 @@ } | ||
execute(args) { | ||
if(this.counter == 0) { | ||
throw new Error('Calling execute on already saturated action'); | ||
} | ||
check.assert(this.counter !== 0, 'Calling execute on already saturated action'); | ||
this.counter -= 1; | ||
return this.action.apply(null, args); | ||
} | ||
/** Specifies expected execution count. Equivalent of providing | ||
* execution count in Action @see constructor | ||
* | ||
* @param {Number} count | ||
* @throws {Error} | ||
* Throws exception if given number is equal 0. | ||
* | ||
* @returns {Expectation} | ||
* Returns expectation owning current action for chaining. | ||
*/ | ||
times(count) { | ||
this.setCounter(count); | ||
return this.owner; | ||
} | ||
} | ||
module.exports = Action; |
'use strict'; | ||
const check = require('./check'); | ||
class Cardinality { | ||
@@ -11,11 +13,8 @@ constructor(min, max) { | ||
set(min, max) { | ||
if((typeof min !== 'number') || (typeof max !== 'number')) { | ||
throw new TypeError('Expected number for both min and max parameters'); | ||
check.type(min, 'number', 'Expected number for min parameter'); | ||
check.type(max, 'number', 'Expected number for max parameter'); | ||
check.assert(min >= 0, 'min parameter can\'t be a negative number'); | ||
if(max >= 0) { | ||
check.assert(min <= max, 'min should be smaller or equal to max'); | ||
} | ||
if((max >= 0) && (max < min)) { | ||
throw new Error('min should be smaller or equal to max'); | ||
} | ||
if(min < 0) { | ||
throw new Error('min parameter can\'t be a negative number'); | ||
} | ||
this.min = min; | ||
@@ -30,8 +29,4 @@ this.max = max; | ||
bump(count) { | ||
if(typeof count !== 'number') { | ||
throw new TypeError('Expected count parameter to be of number type'); | ||
} | ||
if(count <= 0) { | ||
throw new Error('Invalid count value ' + count); | ||
} | ||
check.type(count, 'number', 'Expected count parameter to be of number type'); | ||
check.assert(count > 0, 'Invalid count value ' + count); | ||
this.min += count; | ||
@@ -43,2 +38,6 @@ if(this.max >= 0) { | ||
available() { | ||
return ((this.counter < this.max) || (this.max < 0)) | ||
} | ||
use() { | ||
@@ -45,0 +44,0 @@ this.counter += 1; |
@@ -6,11 +6,11 @@ 'use strict'; | ||
const matcher = require('./matcher'); | ||
const check = require('./check'); | ||
const _ = require('lodash'); | ||
function forceCardinality(min, max) { | ||
if(this.cardinalityForced) { | ||
throw new Error('Cardinality already set for the expectation'); | ||
} else { | ||
this.cardinalityForced = true; | ||
this.cardinality.set(min, max); | ||
} | ||
check.assert(this.actions.length === 0, 'Cardinality should be specified before actions'); | ||
check.assert(!this.cardinalityForced, 'Cardinality already set for the expectation'); | ||
this.cardinalityForced = true; | ||
this.cardinality.set(min, max); | ||
return this; | ||
} | ||
@@ -21,6 +21,7 @@ | ||
if(this.actions.length === 0) { | ||
if(this.count >= 0) { | ||
if(count >= 0) { | ||
this.cardinality.set(count, count); | ||
} else { | ||
this.cardinality.set(1, -1); | ||
this.cardinality.set(1,-1); | ||
this.cardinality.unbound(); | ||
} | ||
@@ -48,3 +49,4 @@ } else if (count >= 0) { | ||
* | ||
* @param {Array} args | ||
* @param {Array} args | ||
* Array of arguments to be used for creation of matcher object | ||
*/ | ||
@@ -71,8 +73,8 @@ constructor(args) { | ||
/** @method isSaturated | ||
* Determines if there is any more action to be executed | ||
* for the expectation. | ||
* Determines if expectation has been already executed maximum | ||
* expected number of times. | ||
* @returns {Boolean} | ||
*/ | ||
isSaturated() { | ||
return _.findIndex(this.actions, a => a.ready()) < 0; | ||
return !this.cardinality.available(); | ||
} | ||
@@ -82,13 +84,13 @@ | ||
* @returns {Boolean} | ||
* Returns true if none action was specified for the expectation or | ||
* if all actions specified are validated, false otherwise. | ||
* Returns true if expectation cardinality is fullfilled, false otherwise. | ||
*/ | ||
validate() { | ||
return this.cardinality.validate(); | ||
// if(this.actions.length === 0) { | ||
// return this.cardinality.validate(); | ||
// } | ||
// return (_.findIndex(this.actions, a => !a.validate()) < 0); | ||
} | ||
/** Specifies expectation cardinality to given number of expected calls. | ||
* | ||
* @param {Number} count | ||
* Expected number of calls | ||
*/ | ||
times(count) { | ||
@@ -98,2 +100,8 @@ return forceCardinality.call(this, count, count); | ||
/** Specifies number of expectation matching calls to be equal or greater | ||
* of given number. | ||
* | ||
* @param {Number} count | ||
* Minimal number of expected matching calls. | ||
*/ | ||
atLeast(count) { | ||
@@ -103,2 +111,8 @@ return forceCardinality.call(this, count, -1); | ||
/** Specifies number of expectation matching calls to be at least 1, | ||
* but not greater than given number. | ||
* | ||
* @param {Number} count | ||
* Maximal number of expected matching calls. | ||
*/ | ||
atMost(count) { | ||
@@ -108,2 +122,9 @@ return forceCardinality.call(this, 1, count); | ||
/** Specifies number of expectation matching calls to lie in given range. | ||
* | ||
* @param {Number} min | ||
* Minimal number of expected matching calls. | ||
* @param {Number} max | ||
* Maximal number of expected matching calls. | ||
*/ | ||
between(min, max) { | ||
@@ -113,24 +134,2 @@ return forceCardinality.call(this, min, max); | ||
/** | ||
* @param {Array} args | ||
* @returns {*} | ||
* If no action was specified for the expectation, will return no value. | ||
* If there is an action to be executed returns result of that execution. | ||
* @throws {Error} | ||
* Throws error if none of specified actions are valid for execution | ||
*/ | ||
execute(args) { | ||
if(!this.cardinality.use()) { | ||
throw new Error('Expectation oversaturated'); | ||
} | ||
if(this.actions.length === 0) { | ||
return; | ||
} | ||
const idx = _.findIndex(this.actions, a => a.ready()); | ||
if(idx < 0) { | ||
throw new Error('Unable to find valid action for execution'); | ||
} | ||
return this.actions[idx].execute(args); | ||
} | ||
/** Creates expectation matcher from provided arguments. | ||
@@ -157,3 +156,3 @@ * | ||
tryUpdateCardinality.call(this, 1); | ||
this.actions.push(new Action(this, action, 1)); | ||
this.actions.push(new Action(action, 1)); | ||
return this; | ||
@@ -173,3 +172,3 @@ } | ||
tryUpdateCardinality.call(this, 2); | ||
this.actions.push(new Action(this, action, 2)); | ||
this.actions.push(new Action(action, 2)); | ||
return this; | ||
@@ -189,7 +188,26 @@ } | ||
tryUpdateCardinality.call(this, -1); | ||
this.actions.push(new Action(this, action, -1)); | ||
this.actions.push(new Action(action, -1)); | ||
return this; | ||
} | ||
/** | ||
* @param {Array} args | ||
* @returns {*} | ||
* If no action was specified for the expectation, will return no value. | ||
* If there is an action to be executed returns result of that execution. | ||
* @throws {Error} | ||
* Throws error if none of specified actions are valid for execution | ||
*/ | ||
execute(args) { | ||
check.assert(this.cardinality.use(), 'Expectation oversaturated'); | ||
if(this.actions.length === 0) { | ||
return; | ||
} | ||
const idx = _.findIndex(this.actions, a => a.available()); | ||
check.assert(idx >= 0, 'Unable to find valid action for execution'); | ||
return this.actions[idx].execute(args); | ||
} | ||
} | ||
module.exports = Expectation; |
@@ -5,7 +5,13 @@ 'use strict'; | ||
const Expectation = require('./expectation'); | ||
const check = require('./check'); | ||
class UnexpectedCall extends Error {}; | ||
/** @class Mock | ||
* | ||
*/ | ||
class Mock { | ||
/** | ||
* | ||
* @param {Object} object | ||
* Object to be mocked. | ||
*/ | ||
@@ -25,6 +31,8 @@ constructor(object) { | ||
/** Bind for a function of a mocked object having at | ||
* least one expectation properly set | ||
/** Bind for all functions of mocked object | ||
* @param {String} functionName | ||
* Name of the function being called | ||
* @throws {UnexpectedCall} | ||
* This function will throw an exception in case if there is no | ||
* matching expectation defined. | ||
*/ | ||
@@ -35,7 +43,7 @@ mockedCall(functionName) { | ||
if(!expectations || expectations.length === 0) { | ||
throw new Error('Unexpected call of ' + functionName); | ||
throw new UnexpectedCall('Unexpected call of ' + functionName); | ||
} | ||
const idx = _.findIndex(expectations, exp => exp.isMatching(args) && !exp.isSaturated()); | ||
if(idx < 0) { | ||
throw new Error('No matching expectation for call ' + functionName + '(' + args.join(',') + ')' ); | ||
throw new UnexpectedCall('No matching expectation for call ' + functionName + '(' + args.join(',') + ')' ); | ||
} else { | ||
@@ -46,10 +54,14 @@ return expectations[idx].execute(args); | ||
/** | ||
/** Creates Expectation for function with given name. | ||
* | ||
* @param {String} functionName | ||
* Name of the function for which the call is expected. | ||
* @throws {Error} | ||
* Error is thrown if given function name doesn't match any of | ||
* functions from mocked object. | ||
* @returns {Expectation} | ||
* Returns newly created Expectation object | ||
*/ | ||
expectCall(functionName) { | ||
if(!_.has(this.originals, functionName)) { | ||
throw new Error('Unknown function ' + functionName); | ||
} | ||
check.assert(_.has(this.originals, functionName), 'Unknown function ' + functionName); | ||
this.expectations[functionName] = this.expectations[functionName] || []; | ||
@@ -61,4 +73,11 @@ let expectation = new Expectation(Array.from(arguments).slice(1)); | ||
/** | ||
/** Verifies if all expectations on mock object were fullfilled. | ||
* | ||
* @throws {Error} | ||
* If no callback provided, method throws Error containing list of mocked | ||
* object functions with unresolved expectations. | ||
* | ||
* @param {Function} done | ||
* Optional callback parameter. If provided, function want throw expection but will | ||
* pass error to callback. If verification succeeds callback is called with null. | ||
*/ | ||
@@ -83,5 +102,3 @@ verify(done) { | ||
/** | ||
* | ||
* @param {Boolean} verify | ||
/** Restores original functions in mocked object. | ||
*/ | ||
@@ -95,2 +112,3 @@ cleanup() { | ||
module.exports = Mock; | ||
exports.Mock = Mock; | ||
exports.UnexpectedCall = UnexpectedCall; |
{ | ||
"name": "jsmock", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Mocking framework for javascript", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "mocha", | ||
"test_coverage": "istanbul cover _mocha" | ||
}, | ||
@@ -9,0 +10,0 @@ "keywords": [ |
@@ -14,43 +14,20 @@ 'use strict'; | ||
// Not a number should throw an error | ||
expect(create.bind(null, Action, this, action, 'bla')).to.throw(TypeError, 'number'); | ||
expect(create.bind(null, Action, this, action, true)).to.throw(TypeError, 'number'); | ||
expect(create.bind(null, Action, this, action, {})).to.throw(TypeError, 'number'); | ||
expect(create.bind(null, Action, action, 'bla')).to.throw(TypeError, 'number'); | ||
expect(create.bind(null, Action, action, true)).to.throw(TypeError, 'number'); | ||
expect(create.bind(null, Action, action, {})).to.throw(TypeError, 'number'); | ||
// Zero value should cause an error | ||
expect(create.bind(null, Action, this, action, 0)).to.throw(Error, 'execution times'); | ||
expect(create.bind(null, Action, this, action, 0.1)).to.throw(Error, 'execution times'); | ||
expect(create.bind(null, Action, action, 0)).to.throw(Error, 'execution times'); | ||
expect(create.bind(null, Action, action, 0.1)).to.throw(Error, 'execution times'); | ||
// Valid non zero numbers should be fine | ||
expect(create.bind(null, Action, this, action, 10)).not.to.throw; | ||
expect(create.bind(null, Action, this, action, 0.9)).not.to.throw; | ||
expect(create.bind(null, Action, action, 10)).not.to.throw; | ||
expect(create.bind(null, Action, action, 0.9)).not.to.throw; | ||
}); | ||
}); | ||
describe('times', () => { | ||
it('Should validate that provided counter is non zero number', () => { | ||
let action = new Action(null); | ||
expect(action.times.bind(action, 'bla')).to.throw(TypeError, 'number'); | ||
expect(action.times.bind(action, true)).to.throw(TypeError, 'number'); | ||
expect(action.times.bind(action, {})).to.throw(TypeError, 'number'); | ||
expect(action.times.bind(action, 0)).to.throw(Error, 'execution times'); | ||
expect(action.times.bind(action, 0.4)).to.throw(Error, 'execution times'); | ||
expect(action.times.bind(action, 10)).not.to.throw; | ||
expect(action.times.bind(action, -1)).not.to.throw; | ||
}); | ||
it('Should return owner', () => { | ||
let expectation = {}; | ||
let action = new Action(expectation); | ||
expect(action.times(3)).to.be.equal(action.owner); | ||
}); | ||
}); | ||
describe('execute', () => { | ||
it('Should execute provided function with given parameters', () => { | ||
let executed = false; | ||
let action = new Action(null, (a, b, c) => { | ||
let action = new Action((a, b, c) => { | ||
executed = true; | ||
@@ -64,3 +41,3 @@ return a + b + c; | ||
it('Should decrement counter on each execute', () => { | ||
let action = new Action(null, () => {}, 5); | ||
let action = new Action(() => {}, 5); | ||
expect(action.counter).to.be.equal(5); | ||
@@ -77,3 +54,3 @@ action.execute(); | ||
it('Should throw exception when executing saturated action', () => { | ||
let action = new Action(null, () => {}, 1); | ||
let action = new Action(() => {}, 1); | ||
action.execute(); | ||
@@ -85,7 +62,7 @@ expect(action.counter).to.be.equal(0); | ||
it('Should return given value for non-function actions', () => { | ||
let action1 = new Action(null, 5, 1); | ||
let action1 = new Action(5, 1); | ||
expect(action1.execute()).to.be.equal(5); | ||
let foo = {a: 1, b: false}; | ||
let action2 = new Action(null, foo, 1); | ||
let action2 = new Action(foo, 1); | ||
expect(action2.execute()).to.be.equal(foo); | ||
@@ -97,3 +74,3 @@ }); | ||
it('Should return true only if action was executed expected number of times', () => { | ||
let action = new Action(null, () => {}, 3); | ||
let action = new Action(() => {}, 3); | ||
expect(action.validate()).to.be.false; | ||
@@ -108,3 +85,3 @@ action.execute(); | ||
it('Should always return true for unbounded actions', () => { | ||
let action = new Action(null, () => {}, -1); | ||
let action = new Action(() => {}, -1); | ||
expect(action.validate()).to.be.true; | ||
@@ -111,0 +88,0 @@ action.execute(); |
@@ -20,2 +20,8 @@ 'use strict'; | ||
}); | ||
it('Should initialize cardinality to expect single execution', () => { | ||
let exp = new Expectation(); | ||
expect(exp.execute.bind(exp)).not.to.throw(Error); | ||
expect(exp.execute.bind(exp)).to.throw(Error, 'oversaturated'); | ||
}); | ||
}); | ||
@@ -48,20 +54,20 @@ | ||
describe('isSaturated', () => { | ||
it('Should return true if there are no ready actions', () => { | ||
it('Should return true if cardinality is not available', () => { | ||
let exp = new Expectation(); | ||
exp.times(3); | ||
expect(exp.isSaturated()).to.be.false; | ||
exp.execute(); | ||
exp.execute(); | ||
expect(exp.isSaturated()).to.be.false; | ||
exp.execute(); | ||
expect(exp.isSaturated()).to.be.true; | ||
exp.actions.push({ready: () => false}); | ||
expect(exp.isSaturated()).to.be.true; | ||
}); | ||
it('Should return false if there is at least one ready actions', () => { | ||
it('Should always return false for unbound cardinalities', () => { | ||
let exp = new Expectation(); | ||
exp.actions.push({ready: () => true}); | ||
exp.actions.push({ready: () => true}); | ||
expect(exp.isSaturated()).to.be.false; | ||
exp.actions[0].ready = () => false; | ||
expect(exp.isSaturated()).to.be.false; | ||
exp.actions[1].ready = () => false; | ||
expect(exp.isSaturated()).to.be.true; | ||
exp.actions[0].ready = () => true; | ||
expect(exp.isSaturated()).to.be.false; | ||
exp.atLeast(2); | ||
for(let i=0; i<1000; ++i) { | ||
exp.execute(); | ||
expect(exp.isSaturated()).to.be.false; | ||
} | ||
}); | ||
@@ -108,30 +114,16 @@ }); | ||
it('Should execute first ready action from the list', () => { | ||
it('Should execute first available action from the list', () => { | ||
let exp = new Expectation(); | ||
exp.atLeast(1); | ||
exp.actions.push({ | ||
ready: () => false, | ||
execute: (args) => 'A1' | ||
}, { | ||
ready: () => true, | ||
execute: (args) => 'A2' | ||
}, { | ||
ready: () => true, | ||
execute: (args) => 'A3' | ||
}); | ||
exp.willOnce('A1').willTwice('A2').willOnce('A3'); | ||
expect(exp.execute()).to.be.equal('A1'); | ||
expect(exp.execute()).to.be.equal('A2'); | ||
expect(exp.execute()).to.be.equal('A2'); | ||
exp.actions[1].ready = () => false; | ||
expect(exp.execute()).to.be.equal('A3'); | ||
}); | ||
it('Should throw expection if no ready action in the list', () => { | ||
it('Should throw expection if no available action in the list', () => { | ||
let exp = new Expectation(); | ||
exp.actions.push({ | ||
ready: () => false, | ||
execute: (args) => 'A1' | ||
}, { | ||
ready: () => false, | ||
execute: (args) => 'A2' | ||
}); | ||
exp.times(3).willOnce('A1').willOnce('A2'); | ||
expect(exp.execute()).to.be.equal('A1'); | ||
expect(exp.execute()).to.be.equal('A2'); | ||
expect(exp.execute.bind(exp)).to.throw(Error, 'valid action'); | ||
@@ -142,20 +134,30 @@ }); | ||
let exp = new Expectation(); | ||
exp.atLeast(1); | ||
exp.actions.push({ | ||
ready: () => true, | ||
execute: (args) => { | ||
expect(args).to.deep.equal([1,2,3]); | ||
return 'A1'; | ||
} | ||
}, { | ||
ready: () => true, | ||
execute: (args) => { | ||
expect(args).to.deep.equal([3,2,1]); | ||
return 'A2'; | ||
} | ||
exp.willOnce((a,b,c) => { | ||
expect([a,b,c]).to.deep.equal([1,2,3]); | ||
return 'A1'; | ||
}); | ||
exp.willOnce((a,b,c) => { | ||
expect([a,b,c]).to.deep.equal([3,2,1]); | ||
return 'A2'; | ||
}); | ||
expect(exp.execute([1,2,3])).to.be.equal('A1'); | ||
exp.actions[0].ready = () => false; | ||
exp.actions[0].available = () => false; | ||
expect(exp.execute([3,2,1])).to.be.equal('A2'); | ||
}); | ||
it('Should throw expection if expectation is already saturated', () => { | ||
let exp = new Expectation(); | ||
exp.atMost(2); | ||
exp.execute(); | ||
exp.execute(); | ||
expect(exp.execute.bind(exp)).to.throw(Error); | ||
}); | ||
it('Should respect forced cardinality even if there are still available actions', () => { | ||
let exp = new Expectation(); | ||
exp.times(2).willOnce(153).willOnce(543).willOnce(123); | ||
expect(exp.execute()).to.be.equal(153); | ||
expect(exp.execute()).to.be.equal(543); | ||
expect(exp.execute.bind(exp)).to.throw(Error); | ||
}); | ||
}); | ||
@@ -186,109 +188,176 @@ | ||
describe.skip('will', () => { | ||
it('Should add new action to the list', () => { | ||
let exp = new Expectation(); | ||
exp.will(() => false); | ||
expect(exp.actions).to.have.length(1); | ||
exp.will(() => 1); | ||
exp.will(() => 2); | ||
expect(exp.actions).to.have.length(3); | ||
}); | ||
describe('actions', () =>{ | ||
describe('willOnce', () => { | ||
it('Should create action with counter set to 1', () => { | ||
let exp = new Expectation(); | ||
exp.willOnce(() => true); | ||
expect(exp.actions).to.have.length(1); | ||
expect(exp.actions[0].counter).to.be.equal(1); | ||
}); | ||
it('Should return newly created action', () => { | ||
let exp = new Expectation(); | ||
let act = exp.will(() => true); | ||
expect(act).to.be.instanceOf(Action); | ||
expect(act).to.be.equal(exp.actions[0]); | ||
expect(act.counter).to.be.equal(1); | ||
it('Should return instance of current expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
expect(exp1.willOnce(() => true)).to.be.equal(exp1); | ||
expect(exp2.willOnce(() => false)).to.be.equal(exp2); | ||
}) | ||
it('Should create action with provided function', () => { | ||
let exp = new Expectation(); | ||
exp.willOnce(() => 4531); | ||
exp.willOnce(() => 'Hello World'); | ||
expect(exp.actions[0].execute()).to.be.equal(4531); | ||
expect(exp.actions[1].execute()).to.be.equal('Hello World'); | ||
}); | ||
}); | ||
it('Should create action with provided function', () => { | ||
let exp = new Expectation(); | ||
let a1 = exp.will(() => 4531); | ||
let a2 = exp.will(() => 'Hello World'); | ||
expect(a1.execute()).to.be.equal(4531); | ||
expect(a2.execute()).to.be.equal('Hello World'); | ||
describe('willTwice', () => { | ||
it('Should create action with counter set to 2', () => { | ||
let exp = new Expectation(); | ||
exp.willTwice(() => true); | ||
expect(exp.actions).to.have.length(1); | ||
expect(exp.actions[0].counter).to.be.equal(2); | ||
}); | ||
it('Should return instance of current expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
expect(exp1.willTwice(() => true)).to.be.equal(exp1); | ||
expect(exp2.willTwice(() => false)).to.be.equal(exp2); | ||
}) | ||
it('Should create action with provided function', () => { | ||
let exp = new Expectation(); | ||
exp.willTwice(() => 4531); | ||
exp.willTwice(() => 'Hello World'); | ||
expect(exp.actions[0].execute()).to.be.equal(4531); | ||
expect(exp.actions[1].execute()).to.be.equal('Hello World'); | ||
}); | ||
}); | ||
it('Should bind action with owning expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
let act1 = exp1.will(() => true); | ||
let act2 = exp2.will(() => false); | ||
expect(act1.owner).to.be.equal(exp1); | ||
expect(act2.owner).to.be.equal(exp2); | ||
describe('willRepeatedly', () => { | ||
it('Should create action with counter set to negative value', () => { | ||
let exp = new Expectation(); | ||
exp.willRepeatedly(() => true); | ||
expect(exp.actions).to.have.length(1); | ||
expect(exp.actions[0].counter).to.be.lessThan(0); | ||
}); | ||
it('Should return instance of current expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
expect(exp1.willRepeatedly(() => true)).to.be.equal(exp1); | ||
expect(exp2.willRepeatedly(() => false)).to.be.equal(exp2); | ||
}) | ||
it('Should create action with provided function', () => { | ||
let exp = new Expectation(); | ||
exp.willRepeatedly(() => 4531); | ||
exp.willRepeatedly(() => 'Hello World'); | ||
expect(exp.actions[0].execute()).to.be.equal(4531); | ||
expect(exp.actions[1].execute()).to.be.equal('Hello World'); | ||
}); | ||
}); | ||
}); | ||
describe('willOnce', () => { | ||
it('Should create action with counter set to 1', () => { | ||
describe('cardinality', () => { | ||
it('Should throw exception on attempt to override existing cardinality', () => { | ||
let exp = new Expectation(); | ||
exp.willOnce(() => true); | ||
expect(exp.actions).to.have.length(1); | ||
expect(exp.actions[0].counter).to.be.equal(1); | ||
exp.times(2); | ||
expect(exp.times.bind(exp,1)).to.throw(Error); | ||
expect(exp.atLeast.bind(exp,3)).to.throw(Error); | ||
expect(exp.atMost.bind(exp,5)).to.throw(Error); | ||
expect(exp.between.bind(exp,1,4)).to.throw(Error); | ||
}); | ||
it('Should return instance of current expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
expect(exp1.willOnce(() => true)).to.be.equal(exp1); | ||
expect(exp2.willOnce(() => false)).to.be.equal(exp2); | ||
}) | ||
it('Should create action with provided function', () => { | ||
it('Should throw expeption if called after at least one action definition', () => { | ||
let exp = new Expectation(); | ||
exp.willOnce(() => 4531); | ||
exp.willOnce(() => 'Hello World'); | ||
expect(exp.actions[0].execute()).to.be.equal(4531); | ||
expect(exp.actions[1].execute()).to.be.equal('Hello World'); | ||
exp.willOnce(() => 2); | ||
expect(exp.times.bind(exp,1)).to.throw(Error); | ||
expect(exp.atLeast.bind(exp,3)).to.throw(Error); | ||
expect(exp.atMost.bind(exp,5)).to.throw(Error); | ||
expect(exp.between.bind(exp,1,4)).to.throw(Error); | ||
}); | ||
}); | ||
describe('willTwice', () => { | ||
it('Should create action with counter set to 2', () => { | ||
it('Should return expectation instance', () => { | ||
let exp = new Expectation(); | ||
exp.willTwice(() => true); | ||
expect(exp.actions).to.have.length(1); | ||
expect(exp.actions[0].counter).to.be.equal(2); | ||
expect(exp.times(3)).to.be.equal(exp); | ||
exp = new Expectation(); | ||
expect(exp.atLeast(2)).to.be.equal(exp); | ||
exp = new Expectation(); | ||
expect(exp.atMost(7)).to.be.equal(exp); | ||
exp = new Expectation(); | ||
expect(exp.between(1,7)).to.be.equal(exp); | ||
}); | ||
it('Should return instance of current expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
expect(exp1.willTwice(() => true)).to.be.equal(exp1); | ||
expect(exp2.willTwice(() => false)).to.be.equal(exp2); | ||
}) | ||
describe('times', () => { | ||
it('Should force cardinality on expectation to exact number of calls', () => { | ||
let exp = new Expectation(); | ||
exp.times(2); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
expect(exp.execute.bind(exp)).to.throw(Error); | ||
}); | ||
}); | ||
it('Should create action with provided function', () => { | ||
let exp = new Expectation(); | ||
exp.willTwice(() => 4531); | ||
exp.willTwice(() => 'Hello World'); | ||
expect(exp.actions[0].execute()).to.be.equal(4531); | ||
expect(exp.actions[1].execute()).to.be.equal('Hello World'); | ||
describe('atLeast', () => { | ||
it('Should force cardinality on expectation to number of calls equal or higher then specified', () => { | ||
let exp = new Expectation(); | ||
exp.atLeast(2); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
for(let i=0; i < 1000; ++i) { | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
} | ||
}); | ||
}); | ||
}); | ||
describe('willRepeatedly', () => { | ||
it('Should create action with counter set to negative value', () => { | ||
let exp = new Expectation(); | ||
exp.willRepeatedly(() => true); | ||
expect(exp.actions).to.have.length(1); | ||
expect(exp.actions[0].counter).to.be.lessThan(0); | ||
describe('atMost', () => { | ||
it('Should put expectation on at least one call', () => { | ||
let exp = new Expectation(); | ||
exp.atMost(6); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
}); | ||
it('Should force cardinality on expectation to number of calls lower or equal then specified', () => { | ||
let exp = new Expectation(); | ||
exp.atMost(2); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
expect(exp.execute.bind(exp)).to.throw(Error); | ||
}); | ||
}); | ||
it('Should return instance of current expectation', () => { | ||
let exp1 = new Expectation(); | ||
let exp2 = new Expectation(); | ||
expect(exp1.willRepeatedly(() => true)).to.be.equal(exp1); | ||
expect(exp2.willRepeatedly(() => false)).to.be.equal(exp2); | ||
}) | ||
it('Should create action with provided function', () => { | ||
let exp = new Expectation(); | ||
exp.willRepeatedly(() => 4531); | ||
exp.willRepeatedly(() => 'Hello World'); | ||
expect(exp.actions[0].execute()).to.be.equal(4531); | ||
expect(exp.actions[1].execute()).to.be.equal('Hello World'); | ||
describe('betweeen', () => { | ||
it('Should thwrow exception if only one parameter given', () => { | ||
let exp = new Expectation(); | ||
expect(exp.between.bind(exp, 1)).to.throw(Error); | ||
}); | ||
it('Should force cardinality on expectation to number of calls in given range', () => { | ||
let exp = new Expectation(); | ||
exp.between(2,4); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.false; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
exp.execute(); | ||
expect(exp.validate()).to.be.true; | ||
exp.execute(); | ||
expect(exp.execute.bind(exp)).to.throw(Error); | ||
}); | ||
}); | ||
}); | ||
}); |
'use strict'; | ||
const expect = require('chai').expect; | ||
const Mock = require('../lib/mock'); | ||
const Mock = require('../lib/mock').Mock; | ||
const UnexpectedCall = require('../lib/mock').UnexpectedCall; | ||
const Expectation = require('../lib/expectation'); | ||
@@ -23,4 +24,4 @@ | ||
let aMock = new Mock(a); | ||
expect(a.foo.bind(a,1,2)).to.be.throw(Error, 'Unexpected call'); | ||
expect(a.bar.bind(a,1,2)).to.be.throw(Error, 'Unexpected call'); | ||
expect(a.foo.bind(a,1,2)).to.be.throw(UnexpectedCall, 'Unexpected call'); | ||
expect(a.bar.bind(a,1,2)).to.be.throw(UnexpectedCall, 'Unexpected call'); | ||
}); | ||
@@ -49,6 +50,16 @@ }); | ||
expect(a.foo(1,2)).to.be.equal(4); | ||
expect(a.bar.bind(a,1,2)).to.be.throw(Error, 'Unexpected call'); | ||
expect(a.bar.bind(a,1,2)).to.be.throw(UnexpectedCall, 'Unexpected call'); | ||
}); | ||
}); | ||
describe('mockedCall', () => { | ||
it('Should throw exception on no matching expectation found', () => { | ||
let a = new A(); | ||
let aMock = new Mock(a); | ||
aMock.expectCall('foo').matching(1,2).willRepeatedly(() => 4); | ||
expect(a.foo(1,2)).to.be.equal(4); | ||
expect(a.foo.bind(a, 2, 1)).to.throw(UnexpectedCall, 'No matching expectation'); | ||
}); | ||
}); | ||
describe('verify', () => { | ||
@@ -55,0 +66,0 @@ it('Should not throw if no expectations were put', () => { |
Sorry, the diff of this file is not supported yet
43661
19
1132