Node.js的测试
测试对于动态语言项目是很重要的,首先需要明确为什么要写测试,你编写测试是为了让自己有信心,对程序能够符合预期的正常工作充满信心,如果出现什么意外事情你就可能能够捕捉到,并且快速明白问题出在哪里,每个测试文件的每一行应当都为这个目标编写。
现代框架已经变得越来越聪明,这是一个好事,但是也意味着你需要更加仔细,这些增强的力量都是由损失明晰而获得的,你的测试可以运行得更快或更可重用,但是这些会让你的信心变得更多还是更少呢?记住:测试上无法投机取巧:There are no points for clever tests。
测试工具集有很多,下面陈列有:
测试框架 (Mocha, Vows, Intern)
一个断言Assertion库包 (Chai, Assert)
Stubs (Sinon)
模块控制 (Mockery, Rewire)
测试框架是进行Node开发首要的事情,这种框架提供一种清晰可伸缩扩展的所有测试的基石,有很多选项和不同特征设置。
Mocha是一个标准的测试框架,易于测试和维护,定制选项很多,相当灵活性感:
describe('yourModuleName',function(){
before(function(){// The before() callback gets run before all tests in the suite. Do one-time setup here.});
beforeEach(function(){// The beforeEach() callback gets run before each test in the suite.});
it('does x when y',function(){// Now... Test!});after(function(){// after() is run after all your tests have completed. Do teardown here.});});
当有了测试框架以后,可以编写一些测试,最容易的方法是使用断言库包:
assert(object.isValid,'tests that this property is true, and throws an error if it is false');
有各种不同风格的库包可供选择,比如TDD BDD和assert() should()等,BDD目前广泛支持的风格, Chai因为支持大部分测试风格而变得很流行,但是如果你只有很少的依赖,那么随着Node.js一起的 simple assertion library也是适用的:
var life = 40 + 2;
expect(life).to.equal(42); // BDD Assertion Style
assert.equal(life, 42); // TDD Assertion Styl
但是,很不幸,断言也是有其局限,当测试更多复杂功能时,我们需要一种更具影响的环境和测试代码的方法,我们需要确定某些函数返回是真,或API调用能获得预期的值,Stub测试工具 Sinon在这方面可以帮助我们:
var callback = sinon.stub();
callback.withArgs(42).returns(1);
callback.withArgs(1).throws("TypeError");
callback(); // No return value, no exception
callback(42); // Returns 1
callback(1); // Throws TypeError
Sinon包括很多其他有用的测试工具,如fake计时器和参数匹配器,除了Stub,还有 Spies用于观察被调用的函数和参数,Mocks 用于设置一些行为预期。
现在你已经准备好测试了,但是还有一个问题:require(),因为大部分调用require都是私有的,没有办法进行stub 断言或其访问外部模块的办法进行,为了真正控制Node测试,一定需要控制require。
有许多不同办法完成这个母的,依赖你需要多强大的功能,Mockery可以让你导出大部分内部模块缓存,然后替代这些模块和我们自己的对象一起加载,测试完毕只要失效mock就可以了。
before(function() {
mockery.enable();
// Allow some ...
mockery.registerAllowable('async');
// ... Control others
mockery.registerMock('../some-other-module', stubbedModule);
});
after(function() {
mockery.deregisterAll();
mockery.disable();
});
Rewire是另外一个流行的mock工具,比Mockery强大得多,使用它你可以得到或设置变量,注入新的代码,替代旧函数,或者修改原始文件,这也许听上去很好,但是随着强大能力到来,你需要重写 重新捆绑私有模块作用域,这会使得你为了测试将代码变得和原始代码有些不一样。