Ultimate Unit Testing Cheat Sheet
Ultimate Unit Testing Cheat Sheet
using mocha/chai/sinon for node.js unit-tests? check out my utility: mocha-stirrer to easily
reuse test components and mock require dependencies
Sinon Chai
Chai
Sinon
Mocha
Sinon Chai
links: GitHub - Chai plugin
Expect/Should (BDD)
links: docs
Chains:
to
be
been
is
that
which
and
has
have
with
at
of
same
Assertions Description
@param{ String }type
@param{ String }message_optional_
The a and an assertions are aliases that can be used either as language chains or to assert a value's
type.
// typeof
.a(type)
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(null).to.be.a('null');
expect(undefined).to.be.an('undefined');
// language chain
expect(foo).to.be.an.instanceof(Foo);
@param{ Number }value
@param{ String }message_optional_
Asserts that the target is greater than value.
expect(10).to.be.above(5);
.above(value)
Can also be used in conjunction with length to assert a minimum length. The benefit being a more
informative error message than if the length was supplied directly.
expect('foo').to.have.length.above(2);
expect([ 1, 2, 3 ]).to.have.length.above(2);
Sets the all flag (opposite of the any flag) later used by the keys assertion.
.all
expect(foo).to.have.all.keys('bar', 'baz');
Sets the any flag, (opposite of the all flag) later used in the keys assertion.
.any
expect(foo).to.have.all.keys('bar', 'baz');
Asserts that the target is an arguments object.
.exist
expect(foo).to.exist;
expect(bar).to.not.exist;
expect(baz).to.not.exist;
Asserts that the target is false.
.false expect(false).to.be.false;
expect(0).to.not.be.false;
Assertions Description
@param{ Object | String | Number }obj
@param{ String }message_optional_
The include and contain assertions can be used as either property based language chains or as
methods to assert the inclusion of an object in an array or a substring in a string. When used as
.include(value)
language chains, they toggle the contains flag for the keys assertion.
expect([1,2,3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
@param{ String }object
@param{ String }propertyname
@param{ String }message_optional_
.increase(function) Asserts that a function increases an object property
var obj = { val: 10 };
var fn = function() { obj.val = 15 };
expect(fn).to.increase(obj, 'val');
@param{ Constructor }constructor
@param{ String }message_optional_
Asserts that the target is an instance of constructor.
.instanceof(constructor) var Tea = function (name) { this.name = name; }
, Chai = new Tea('chai');
expect(Chai).to.be.an.instanceof(Tea);
expect([ 1, 2, 3 ]).to.be.instanceof(Array);
Sets the itself flag, later used by the respondTo assertion.
function Foo() {}
Foo.bar = function() {}
.itself Foo.prototype.baz = function() {}
expect(Foo).itself.to.respondTo('bar');
expect(Foo).itself.not.to.respondTo('baz');
@param{ String... | Array | Object }keys
Asserts that the target contains any or all of the passed-in keys. Use in combination with any, all,
contains, or have will affect what will pass.
When used in conjunction with any, at least one key that is passed in must exist in the target object.
This is regardless whether or not the have or contain qualifiers are used. Note, either any or all
should be used in the assertion. If neither are used, the assertion is defaulted to all.
When both all and contain are used, the target object must have at least all of the passed-in keys but
may have more keys not listed.
When both all and have are used, the target object must both contain all of the passed-in keys AND
the number of keys in the target object must match the number of keys passed in (in other words, a
.keys(key1, [key2], [...]) target object must have all and only all of the passed-in keys).
Asserts that the target's length property has the expected value.
expect([ 1, 2, 3]).to.have.length(3);
expect('foobar').to.have.length(6);
Can also be used as a chain precursor to a value comparison for the length property.
.length(value)
expect('foo').to.have.length.above(2);
expect([ 1, 2, 3 ]).to.have.length.above(2);
expect('foo').to.have.length.below(4);
expect('foo').to.have.length.below(4);
expect([ 1, 2, 3 ]).to.have.length.below(4);
expect('foo').to.have.length.within(2,4);
expect([ 1, 2, 3 ]).to.have.length.within(2,4);
Assertions Description
@param{ RegExp }RegularExpression
@param{ String }message_optional_
.match(regexp)
Asserts that the target matches a regular expression.
expect('foobar').to.match(/^foo/);
@param{ Array }set
@param{ String }message_optional_
Asserts that the target is a superset of set, or that the target and set have the same strictly-equal
(===) members. Alternately, if the deep flag is set, set members are compared for deep equality.
.members(set) expect([1, 2, 3]).to.include.members([3, 2]);
expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
expect([4, 2]).to.have.members([2, 4]);
expect([5, 2]).to.not.have.members([5, 2, 1]);
expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
@param{ Number }value
@param{ String }message_optional_
Asserts that the target is less than or equal to value.
expect(5).to.be.at.most(5);
.most(value)
Can also be used in conjunction with length to assert a maximum length. The benefit being a more
informative error message than if the length was supplied directly.
expect('foo').to.have.length.of.at.most(4);
expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
Negates any of assertions following in the chain.
expect(foo).to.not.equal('bar');
.not
expect(goodFn).to.not.throw(Error);
expect({ foo: 'baz' }).to.have.property('foo').and.not.equal('bar');
Asserts that the target is null.
.null
expect(null).to.be.null;
expect(undefined).not.to.be.null;
.ok Asserts that the target is truthy.
@param{ String }name
@param{ String }message_optional_
.ownProperty(name)
Asserts that the target has an own property name.
expect('test').to.have.ownProperty('length');
Assertions Description
@param{ String }name
@param{ Mixed }value(optional)
@param{ String }message_optional_
Asserts that the target has a property name, optionally asserting that the value of that property is
strictly equal to value. If the deep flag is set, you can use dot- and bracket-notation for deep
references into objects and arrays.
// simple referencing
var obj = { foo: 'bar' };
expect(obj).to.have.property('foo');
expect(obj).to.have.property('foo', 'bar');
// deep referencing
var deepObj = {
green: { tea: 'matcha' }
, teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
};
expect(deepObj).to.have.deep.property('green.tea', 'matcha');
.property(name,
expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
[value])
expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
You can also use an array as the starting point of a deep.property assertion, or traverse nested
arrays.
var arr = [
[ 'chai', 'matcha', 'konacha' ]
, [ { tea: 'chai' }
, { tea: 'matcha' }
, { tea: 'konacha' } ]
];
expect(arr).to.have.deep.property('[0][1]', 'matcha');
expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
Furthermore, property changes the subject of the assertion to be the value of that property from the
original object. This permits for further chainable assertions on that property.
expect(obj).to.have.property('foo').that.is.a('string');
expect(deepObj).to.have.property('green').that.is.an('object').that.deep.equals({ tea: 'matcha' });
expect(deepObj).to.have.property('teas').that.is.an('array').with.deep.property('[2]').that.deep.equals({
tea: 'konacha' });
@param{ String }method
@param{ String }message_optional_
Asserts that the object or class target will respond to a method.
Klass.prototype.bar = function(){};
.respondTo(method) expect(Klass).to.respondTo('bar');
expect(obj).to.respondTo('bar');
To check if a constructor will respond to a static function, set the itself flag.
Klass.baz = function(){};
expect(Klass).itself.to.respondTo('baz');
@param{ Function }matcher
@param{ String }message_optional_
.satisfy(method)
Asserts that the target passes a given truth test.
expect(1).to.satisfy(function(num) { return num > 0; });
@param{ String }string
@param{ String }message_optional_
.string(string)
Asserts that the string target contains another string.
expect('foobar').to.have.string('bar');
Assertions Description
@param{ ErrorConstructor }constructor
@param{ String | RegExp }expectederror message
@param{ String }message_optional_
@see: [https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types]()
Asserts that the function target will throw a specific error, or specific type of error (as determined
using instanceof), optionally with a RegExp or string inclusion test for the error's message.
.throw(constructor) expect(fn).to.throw(ReferenceError);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ReferenceError, /bad function/);
expect(fn).to.throw(err);
expect(fn).to.not.throw(new RangeError('Out of range.'));
Please note that when a throw expectation is negated, it will check each parameter independently,
starting with error constructor type. The appropriate way to check for the existence of a type of error
but for a message that does not match is to use and.
expect(fn).to.throw(ReferenceError) .and.not.throw(/good function/);
Asserts that the target is true.
.true expect(true).to.be.true;
expect(1).to.not.be.true;
Asserts that the target is undefined.
.undefined expect(undefined).to.be.undefined;
expect(null).to.not.be.undefined;
@param{ Number }startlowerbound inclusive
@param{ Number }finishupperbound inclusive
@param{ String }message_optional_
Asserts that the target is within a range.
expect(7).to.be.within(5,10);
.within(start, finish)
Can also be used in conjunction with length to assert a length range. The benefit being a more
informative error message than if the length was supplied directly.
expect('foo').to.have.length.within(2,4);
expect([ 1, 2, 3 ]).to.have.length.within(2,4);
Sinon
links: sinon home , docs , code
Spy
Creates an anonymous function that records arguments, this value, exceptions and return values
for all calls.
Matchers
Matchers method Description
sinon.match(number) Requires the value to be == to the given number.
Requires the value to be a string and have the
sinon.match(string)
expectation as a substring.
Requires the value to be a string and match the given
sinon.match(regexp)
regular expression.
Requires the value to be not null or undefined and have
sinon.match(object) at least the same properties as expectation. This supports
nested matchers.
sinon.match(function) See [custom matchers](#sinonCustomMatchers)
sinon.match.any Matches anything.
sinon.match.defined Requires the value to be defined.
sinon.match.truthy Requires the value to be truthy.
sinon.match.falsy Requires the value to be falsy.
sinon.match.bool Requires the value to be a boolean.
sinon.match.number Requires the value to be a number.
sinon.match.string Requires the value to be a string.
sinon.match.object Requires the value to be an object.
sinon.match.func Requires the value to be a function.
sinon.match.array Requires the value to be an array.
sinon.match.regexp Requires the value to be a regular expression.
sinon.match.date Requires the value to be a date object.
sinon.match.same(ref) Requires the value to strictly equal ref.
Matchers method Description
Requires the value to be of the given type, where type can
sinon.match.typeOf(type) be one of "undefined", "null", "boolean", "number",
"string", "object", "function", "array", "regexp" or "date".
sinon.match.instanceOf(type) Requires the value to be an instance of the given type.
Requires the value to define the given property. The
property might be inherited via the prototype chain. If the
sinon.match.has(property[,
optional expectation is given, the value of the property is
expectation])
deeply compared with the expectation. The expectation
can be another matcher.
Same as sinon.match.has but the property must be
sinon.match.hasOwn(property[,
defined by the value itself. Inherited properties are
expectation])
ignored.
Combining matchers All matchers implement and and or. This allows to logically combine mutliple
matchers. The result is a new matchers that requires both (and) or one of the matchers (or) to
return true. var stringOrNumber = sinon.match.string.or(sinon.match.number);
before(function() {
// runs before all tests in this block
})
after(function(){
// runs after all tests in this block
})
beforeEach(function(){
hooks
// runs before each test in this block
})
afterEach(function(){
// runs after each test in this block
})
// test cases
})
Each hook also accepting done as first parameter to support async methods
describe('Array', function(){
describe('#indexOf()', function(){
Pending tests it('should return -1 when the value is not present');
})
})
describe('Array', function(){
describe.only('#indexOf()', function(){
...
})
})