随着前端项目复杂程度的增加,单元测试成为了前端开发过程中代码质量控制不可或缺的一部分。与后端单元测试有所不同的地方是前端开发中经常会出现异步请求的场景。针对这种情况,单元测试也就需要加入异步测试的方法。
以前端测试框架Jest为例。
Jest对于普通函数的测试方式如下:
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});
Jest对于回调函数类型的异步测试的使用方式如下:
test('the data is peanut butter', done => {
function callback(data) {
expect(data).toBe('peanut butter');
done();
}
fetchData(callback);
});
异步测试是通过传递一个done函数给回调函数,再由回调函数中的异步函数执行完毕后主动触发该done函数来实现的。这样子就可以保证后续测试会在异步测试执行完毕后才开始执行测试。
下面是我对于这种测试方式的模拟实现。
var testArr = [];//测试数组
var testResult = [];//测试结果数组
//断言对象
var assert = function(data){
this.val = data;
};
//断言对象的方法
assert.prototype.toBe = function(goal){
var result;
if(this.val === goal){
result = 'true';
}else{
result = 'false';
}
testResult[testResult.length - 1].resultList.push(result);
};
/**
* 测试函数,向测试数组中添加测试
* @param title 测试标题
* @param callback 测试回调函数
*/
function test(title, callback){
testArr.push({title: title, callback: callback});
}
/**
* 返回一个断言对象实例
* @param data 要测试的数据
* @return {assert} 断言对象实例
*/
function expect(data){
return new assert(data);
}
/**
* 测试方法,使用回调遍历执行测试数组中的测试项
* @return {boolean}
*/
function testing(){
if(testArr.length === 0){
//当测试数组为空时,打印测试结果
printLog();
return false;
}
//取出测试数据第一项
var _test = testArr.shift();
//向测试结果数组中添加一项测试结果
testResult.push({title: _test.title, resultList:[]});
//当回调函数有参数时,将testing方法传递给回调函数,用以实现异步函数的测试
if(_test.callback.length === 1){
//测试异步函数
_test.callback(testing);
}else{
//测试同步函数
_test.callback();
testing();
}
}
/**
* 遍历测试结果数组,打印测试结果
*/
function printLog(){
testResult.forEach(function(e, i){
console.log((i+1)+"、"+e.title);
e.resultList.forEach(function(o){
console.log(o)
})
});
}
/**
* 调用testing函数开始测试
*/
function startTest(){
testing();
}
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../jquery-1.7.1.js"></script>
<script src="test.js"></script>
</head>
<body>
<script>
test("first test", function(){
expect("tom").toBe("tom");
});
test("second test", function(done){
$.get("http://localhost:3000/test", function(data){
expect(data).toBe(123);
done();
});
});
test("third test", function(){
expect(123).toBe("abc");
});
startTest();
</script>
</body>
</html>
这段代码实现的关键是JavaScript提供了获取函数形参个数的方式,这样我们才能轻松的实现根据函数形参个数传递相应的参数。
function a(b){}
console.log(a.length)// 1
function c(d,e){}
console.log(c.length)// 2