unit.js是一个javascript断言库,该库可以在node.js与浏览器上运行。它适用于任何测试runner和单元测试框架,如mocha、jasmine、karma、protractor(角度应用程序的E2E测试框架)、qunit等。

为了使用户按自己喜欢的方式编写单元测试,unit.js提供了一个很棒的API,该API拥有如下库的接口:

+ Unit.js (fluent style inpired by Atoum)
+ Assert (of Node.js)
+ Must.js
+ Should.js
+ Sinon.js
+ other friendly features.

为了使这篇文档相对简单,所有示例都使用mocha来运行(除了与其他测试runner相关的实例)。Unit.js支持依赖注入,并且可以扩展为一个认证系统的插件。这使Unit.js学习曲线非常短。 断言列表在API文档中有完整记录,断言表达式如下:

test.string('hello');
test.object(user).hasProperty('email');
test.array(fruit).hasValue('kiwi');

几个样式(Serveral styles)

基本样式(Basic)



var obj = {
message : 'hello',
name : 'Nico'
};
var str = 'Hello world';
// Structure of a request object.
// By example, provided by Express framework and other modules.
var req = {
headers: {
'content-type': 'application/json'
}
};
test.object(obj).hasProperty('name');
test.object(obj).hasProperty('message', 'hello');
test.string(str).startsWith('Hello');
test.string(str).contains('world');
test.string(str).match(/[a-zA-Z]/);
test.value(req).hasHeader('content-type');
test.value(req).hasHeader('content-type', 'application/json');
// or
test.value(req).hasHeaderJson();

流样式(Fluent)

var obj = {message: 'hello', name: 'Nico'};
var str = 'Hello world';
// Structure of a request object.
// By example, provided by Express framework and other modules.
var req = {
headers: {
'content-type': 'application/json'
}
};
test
.object(obj)
.hasProperty('name')
.hasProperty('message', 'hello')
.string(str)
.startsWith('Hello')
.contains('world')
.match(/[a-zA-Z]/)
.value(req)
.hasHeader('content-type')
// more precise
.hasHeader('content-type', 'application/json')
// or shortcut
.hasHeaderJson()
;

表达式样式(Expressive)

var obj = {message: 'hello', name: 'Nico'};
var trigger = function(){
throw new Error('Whoops !');
};
test
.object(obj)
.hasProperty('name')
.hasProperty('message', 'hello')
.when('Add "job" property', obj.job = 'developper')
.then(function(){
test.object(obj).hasProperty('job', 'developper');
})
.case('Delete all properties', function() {
test
.when(function() {
delete obj.name;
delete obj.message;
delete obj.job;
})
.then(function(){
test.object(obj).isEmpty();
})
;
})
.if(obj.message = 'Hello world !')
.and(obj.name = 'say hello')
.string(obj.message)
.startsWith('Hello')
.endsWith('world !')
.notContains('foobar')
.given(obj = new Date(2014, 02))
.date(obj)
.isBefore(new Date(2020, 12))
.isAfter(new Date(2010, 01))
.isBetween(new Date(2014, 01), new Date(2014, 12))
.then('Test the exception')
.exception(trigger)
.hasMessage('Whoops !')
.hasMessage(/whoops/i)
.isInstanceOf(Error)
// or
.error(trigger)
.hasMessage('Whoops !')
.hasMessage(/whoops/i)
;

集成好的断言库



Assert



// test 'string' type
test.assert(typeof 'foobar' == 'string');
// then that actual value '==' expected value
test.assert.equal('foobar', 'foobar');
// then that actual value '===' expected value
test.assert.strictEqual('foobar', 'foobar');
// this shortcut works also like this
var assert = test.assert;
// test 'string' type
assert(typeof 'foobar' == 'string');
// then that actual value '==' expected value
assert.equal('foobar', 'foobar');
// then that actual value '===' expected value
assert.strictEqual('foobar', 'foobar');

assert帮助文档:

​点击打开链接​


Must.js



/ test 'string' type
test.must('foobar').be.a.string();
// then that actual value '==' expected value
test.must('foobar' == 'foobar').be.true();
// then that actual value '===' expected value
test.must('foobar').be.equal('foobar');
// Must.js library (alternative style)
var must = test.must;
// test 'string' type
('foobar').must.be.a.string();
// then that actual value '==' expected value
('foobar' == 'foobar').must.be.true();
// then that actual value '===' expected value
('foobar').must.be.equal('foobar');
// this shortcut works also like this
// test 'string' type
must('foobar').be.a.string();
// then that actual value '==' expected value
must('foobar' == 'foobar').be.true();
// then that actual value '===' expected value
must('foobar').be.equal('foobar');

Must.js帮助文档:

​点击打开链接​


Should.js

// test 'string' type
test.should('foobar').be.type('string');
// then that actual value '==' expected value
test.should('foobar' == 'foobar').be.ok;
// then that actual value '===' expected value
test.should('foobar').be.equal('foobar');
// Should.js library (alternative style)
var should = test.should;
// test 'string' type
('foobar').should.be.type('string');
// then that actual value '==' expected value
('foobar' == 'foobar').should.be.ok;
// then that actual value '===' expected value
('foobar').should.be.equal('foobar');
// this shortcut works also like this
// test 'string' type
should('foobar').be.type('string');
// then that actual value '==' expected value
should('foobar' == 'foobar').be.ok;
// then that actual value '===' expected value
should('foobar').be.equal('foobar');

Should.js帮助文档:

​点击打开链接​



Sinon.js


Spy:


var spy = test.spy();
spy(42);
test.assert(spy.withArgs(42).calledOnce);

Mock:


function once(fn) {
var
returnValue,
called = false
;
return function () {
if (!called) {
called = true;
returnValue = fn.apply(this, arguments);
}
return returnValue;
};
};
var myAPI = { method: function () {} };
var mock = test.mock(myAPI);
mock
.expects('method')
.once()
.returns(42)
;
var proxy = once(myAPI.method);
test.number(proxy()).is(42);
mock.verify();

Sandbox:


it('test using sandbox', test.sinon.test(function () {
var myAPI = {
method: function () {}
};
var mockMyApi = this.mock(myAPI).expects('method').once().returns(42);
var proxy = once(myAPI.method);
test.number(proxy()).isIdenticalTo(42);
mockMyApi.verify();
}));

Sinon.js的帮助文档:

​点击打开链接​