如何为使用Promise规范的接口写测试用例
nodeJs为Javascript引入了单元测试的概念。单元测试能够帮助我们更好的提高代码质量,让BUG在代码编写的时候即被消灭掉。
同步单元测试:
var should = require('should');/*断言库*/
function A(x){
return x ? true : false
}
describe('function A test',function(){
it('when x = 1,return true',function(){
A(1).should.be.true;
});
it('when x = 0,return false',function(){
A(0).should.be.false;
});
});
异步单元测试:
var should = require('should');
var fs = require('fs');
describe('fs.readFile is ok',function(done){
fs.readFile('/test.txt','utf-8',function(err,data){
should.not.exist(err);
done();
});
});
同步与异步测试区别就在于 describe 的回调函数是否有形参 done
Promise 规范的目的是为了让程序员能以同步代码的形式来写异步代码。直观的表现就是,本来无限嵌套的回调函数变成了链式调用。
Promise规范来书写的接口:
var Promise = require('promise');
var fs = require('fs');
/*Promise的实现方式有很多种,这里使用promise库*/
function fileRead(filePath,encode){
return new Promise(function(resole,reject){
fs.readFile(filePath,encode?encode:'utf-8',function(err,data){
if(err){
reject(err);
}else{
resolve(data);
}
});
});
}
/*调用*/
fileRead('/test.txt')
.then(function(data){
//do something with data
...
},function(err){
//log err
...
});
/*测试*/
var should = require('should');
describe('fileRead is ok',function(done){
fileRead('/test.txt')
.then(function(result){
result.should.be.String;
done();
},function(err){
done(err);
})
});
跑一下测试。嗯,好像没问题。收拾东西下班!!!
###wait a minute
注意测试代码中这一行代码
result.should.be.String;
这行代码的目的是检测 result 是否是字符串。如果 result 不是字符串,那应该会被测试框架捕获到。
稍微修改下
[1,2,3].should.be.String;
/*这里只是为了测试错误是否能被捕获到,所以用[1,2,3]替换了result*/
###纳尼!!!
测试如我所料没有通过,但是报的错误是 timeout 是什么鬼啊!!!
好像一不小心又发现了一个知识点啊。嗯,今天晚上一定要把它解决了。
兴奋的我带着电脑回到家中玩了一个晚上的魔兽。。。
明天周六,我花一天时间肯定能搞定!!!(这话估计也就我自己会信╮(╯▽╰)╭)
就这样,这个问题陪伴着我度过了一个愉快而又充实的3.8妇女节(什么鬼。。。摔)
周一上班的路上突然想到会不会跟 promise 的实现有关。来到公司,遂看了 promise 的core.js代码。
经过一番倒腾,大致理顺了 promise 的核心思路。 promise 是通过内部的一个handler构造函数来控制回调链的传递。并且你所传入的回调函数并非直接由handler控制,而是由两个叫 resolve 和 reject 的方法控制。
所以我猜测错误可能是被 promise 捕获了,但是没有被测试框架捕获。(不要问我为什么,我也不知道)
于是用尽了各种办法,最终还是没能证明上面的猜测(一股弱者的气息。。。)
###google大法好
这是stackoverflow上相同的问题,证实了我的猜测。
被采纳的答案其实也没能说清其中原由。
答案中引用的when.js的doc文档中也是一句话带过 Errors in an asynchronous operation always occur in a different call stack than the the one that initiated the operation
修改测试代码:
var should = require('should');
describe('fileRead is ok',function(done){
fileRead('/test.txt')
.then(function(result){
[1,2,3].should.be.String;
done();
},done).catch(done);
});
顺利捕获断言错误。至于为什么promise阻断了测试框架捕获错误,还有待研究。