JS学习之Jasmine中的timeout

来源:互联网 发布:js ajax done 编辑:程序博客网 时间:2024/06/09 15:36

最近被Jasmine中的异步超时弄得崩溃了,具体问题就是setTimeout,有时导致测试用例超时,有时又没有等待足够的时间。因此下定决心研究一下Jasmine中异步超时的用法。

首先,看看jasmine文档给的例子:

describe("long asynchronous specs", function() {    var originalTimeout;    beforeEach(function() {        originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;        jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;    });    it("testTimeout", function(done) {        setTimeout(function() {            done();        }, 9000);    });    afterEach(function() {        jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;    });});

这个例子非常简单,运行testTimeout这个用例时也大约停顿了9秒,测试结果为:

SPEC HAS NO EXPECTATIONS testTimeout

这个结果还算正常,因为测试用例中没有任何测试期望,如果加上expect(1).toEqual(1);语句,就不会提示上面的信息了。

接下来,仿照上面的代码写了一个例子:

describe("TimeOutTest", function() {    var value = 0;    beforeEach(function() {        jasmine.clock().install();    });    afterEach(function() {        jasmine.clock().uninstall();    });    it("testTimeout", function(done) {        console.log("start testTimeout ...");        expect(value).toEqual(0);        setTimeout(function() {            console.log("timeout callback");            value++;            done();        }, 2000);        console.log("after timeout");        expect(value).toEqual(1);    });});

但结果出乎意料之外,有两个错误:

  1. expect(value).toEqual(1); 这句failed,此时value的值为0。仔细一想,value值确实是0,因为setTimeout函数虽然设置了超时回调,但这个函数本身并不会阻塞在这儿,而是会接着往下执行。
  2. 提示错误:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

这个错误就有些不理解了,和上一个例子的代码差不多,为什么这个不会回调到超时callback呢?如果回调了,执行了done(); 就不会出现上述的超时错误。

再研究jasmine的例子,将上述的例子修改如下:

describe("TimeOutTest", function() {    var value = 0;    beforeEach(function() {        jasmine.clock().install();    });    afterEach(function() {        jasmine.clock().uninstall();    });    it("testTick", function(done) {        console.log("start testTick ...");        expect(value).toEqual(0);        setTimeout(function() {            console.log("timeout callback");            value++;            done();        }, 2000);        console.log("after timeout");        jasmine.clock().tick(2001);        expect(value).toEqual(1);    });});

这次测试用例运行正确,秘诀就在于引入了jasmine.clock().tick()函数,这个函数运行会有两个后果:

  1. 它会阻塞javascript代码的执行,相当于C程序中的sleep函数。
  2. 超时之后回调到setTimeout中的设置的callback,在上面的例子中,会执行到value++,所以expect(value).toEqual(1);这句测试得以通过。

再回头看第二个例子,问题出在哪儿呢?原因在于jasmine.clock().install();这句话,它实际上会改写系统的setTimeout函数,它将会同步等待一段时间过去,这个时候就需要借助于jasmine.clock().tick()来休眠一段时间。如果没有这句话,测试用例会等待,直到jasmine.DEFAULT_TIMEOUT_INTERVAL超时。如果第三个例子中jasmine.clock().tick(2001);改为小于2000的一个值,会是什么情况呢?答案就是出现jasmine.DEFAULT_TIMEOUT_INTERVAL超时,也就是等待的时间不够长,不会触发setTimeout超时。

总结:

  1. jasmine.clock().install()/jasmine.clock().uninstall()要和jasmine.clock().tick()配合使用。

以上的完整代码可参考我在github上的项目jsdemo.

0 0