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强大得多,使用它你可以得到或设置变量,注入新的代码,替代旧函数,或者修改原始文件,这也许听上去很好,但是随着强大能力到来,你需要重写 重新捆绑私有模块作用域,这会使得你为了测试将代码变得和原始代码有些不一样。

Node.js教程系列

Node.js编程之道