原文地址:http://www.monring.com/front_end/unit-test-jasmine-asyncTest.html
Jasmine是一个很好的前端单元测试框架,之前也用Jasmine和Qunit进行了一个比较。但Jasmine的异步测试虽然比较灵活,但还是多少有些麻烦,如果我们的这类异步测试比较多,那么重复代码也就上升了,为了代码的质量我们选择封装一下,让它拥有和Qunit一样方便的异步测试调用。先看啊可能整个代码需要这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
describe(
"Asynchronous specs"
,
function
() {
var
value, flag;
it(
"should support async execution of test preparation and exepectations"
,
function
() {
/**
Specs are written by defining a set of blocks with calls to `runs`, which usually finish with an asynchronous call.
*/
runs(
function
() {
flag =
false
;
value = 0;
setTimeout(
function
() {
flag =
true
;
}, 500);
});
/**
The `waitsFor` block takes a latch function, a failure message, and a timeout.
The latch function polls until it returns true or the timeout expires, whichever comes first. If the timeout expires, the spec fails with the error message.
*/
waitsFor(
function
() {
value++;
return
flag;
},
"The Value should be incremented"
, 750);
/**
Once the asynchronous conditions have been met, another `runs` block defines final test behavior. This is usually expectations based on state after the asynch call returns.
*/
runs(
function
() {
expect(value).toBeGreaterThan(0);
});
});
});
|
对方法封装后我们需要的是这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
describe(
"Asynchronous specs"
,
function
() {
var
value;
it(
"should support async execution of test preparation and exepectations"
,
function
() {
value = 0;
stop();
setTimeout(
function
() {
start();
expect(value).toBeGreaterThan(0);
}, 500);
});
//或者这样
asyncTest(
"should support async execution of test preparation and exepectations"
,
function
() {
value = 0;
setTimeout(
function
() {
start();
expect(value).toBeGreaterThan(0);
}, 500);
});
});
|
这样看上去整洁很多,那么看看我们如何封装这个异步测试方法吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
jasmine.extendAsync = (
function
(){
var
_flag =
true
;
return
{
start:
function
() {
_flag =
true
;
},
stop:
function
(optionalTimeoutMessage, optionalTimeout) {
var
timeoutMessage =
null
,
timeout =
null
;
_flag =
false
;
for
(
var
i = 0; i < arguments.length; i++) {
var
arg = arguments[i];
switch
(
typeof
arg) {
case
'string'
:
timeoutMessage = arg;
break
;
case
'number'
:
timeout = arg;
break
;
}
}
waitsFor(
function
() {
return
_flag;
}, timeoutMessage ||
'execute timeout.'
, timeout || jasmine.getEnv().defaultTimeoutInterval);
},
asyncTest:
function
(desc, func) {
var
_this =
this
;
jasmine.getEnv().it(desc,
function
() {
_this.stop(desc);
func.call();
});
}
};
}());
jasmine.extendExecute = (
function
(){
var
_flag=
false
;
return
{
isExecuted:
function
() {
return
_flag;
},
execute:
function
() {
if
(!_flag) {
jasmine.getEnv().execute();
_flag =
true
;
}
}
};
}());
var
stop = jasmine.extendAsync.stop;
jasmine.stop = stop;
var
start =
function
() {
if
(jasmine.extendExecute.isExecuted()) {
jasmine.extendAsync.start();
}
else
{
jasmine.extendExecute.execute();
}
};
jasmine.start = start;
var
asyncTest = jasmine.extendAsync.asyncTest;
jasmine.asyncTest = asyncTest;
|
jasmine.extendExecute赋予到start方法是为了初始化Jasmine的时候直接用start(); 例如我们如果用RequireJs,那么他的测试如何就应该这样开始。
require(testModules.URLs, jasmine.start)。
当然这里的异步封装主要还是用来测试RequireJS模块之间调用的,而对于真正Ajax的测试我觉得需要要到它。这个后面我以后再分享。