Javascript测试框架Jasmine(六):异步代码测试

模拟Timeout

Jasmine Clock 可以用来测试setTimeoutsetInterval 的回调操作。它使回调函数同步执行,当Clock的时间超过timer的时间,回调函数会被触发一次。这使依赖于时间的代码更加易于测试。

Jasmine Clock使用jasmine.clock().install 在需要调用timer函数的spec和suite中初始化。在执行完测试的时候,一定要卸载Clock来还原timer函数。使用jasmine.clock().tick 设置时间以使注册的回调触发。

describe("Jasmine Clock 测试", function() {
    var timerCallback;

    beforeEach(function() {
        timerCallback = jasmine.createSpy("timerCallback");
        jasmine.clock().install();
    });

    afterEach(function() {
        jasmine.clock().uninstall();
    });

    it("同步触发setTimeout", function() {
        setTimeout(function() {
            timerCallback();
        }, 100);

        expect(timerCallback).not.toHaveBeenCalled();

        jasmine.clock().tick(101);

        expect(timerCallback).toHaveBeenCalled();
    });

    it("同步触发setInterval", function() {
        setInterval(function() {
            timerCallback();
        }, 100);

        expect(timerCallback).not.toHaveBeenCalled();

        jasmine.clock().tick(101);
        expect(timerCallback.calls.count()).toEqual(1);

        jasmine.clock().tick(50);
        expect(timerCallback.calls.count()).toEqual(1);

        jasmine.clock().tick(50);
        expect(timerCallback.calls.count()).toEqual(2);
    });
});

在线演示

异步支持

Jasmine支持测试需要执行异步操作的specs,调用beforeEach , it , 和afterEach 的时候,可以带一个可选的参数done ,当spec执行完成之后需要调用done 来告诉Jasmine异步操作已经完成。默认Jasmine的超时时间是5s,可以通过全局的jasmine.DEFAULT_TIMEOUT_INTERVAL 设置。

describe("Jasmine 异步测试演示", function() {
    var value;

    beforeEach(function(done) {
        setTimeout(function() {
            value = 0;
            done();
        }, 1);
    });

    it("should support async execution of test preparation and expectations", function(done) {
        value++;
        expect(value).toBeGreaterThan(0);
        done();
    });

    describe("5秒钟", function() {
        var originalTimeout;
        beforeEach(function() {
            originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
            jasmine.DEFAULT_TIMEOUT_INTERVAL = 6000;
        });

        it("takes a long time", function(done) {
            setTimeout(function() {
                done();
            }, 5000);
        });

        afterEach(function() {
            jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
        });
    });
});

在线测试,注意要等5s才有结果。

测试ajax回调

jasmine-ajax插件(https://github.com/pivotal/jasmine-ajax)用来模拟测试ajax。注意这是个单独的文件,需要额外引用。目前感觉这个用处不大(不然不会以插件的形式出现,呵呵),具体就不说了,这是官方文档:http://jasmine.github.io/2.0/ajax.html,下面直接看个例子:

describe("mocking ajax", function() {

    describe("suite wide usage", function() {

        beforeEach(function() {
            jasmine.Ajax.install();
        });

        afterEach(function() {
            jasmine.Ajax.uninstall();
        });

        it("specifying response when you need it", function() {
            var doneFn = jasmine.createSpy("success");

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(arguments) {
                if (this.readyState == this.DONE) {
                    doneFn(this.responseText);
                }
            };

            xhr.open("GET", "/some/cool/url");
            xhr.send();

            expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url');
            expect(doneFn).not.toHaveBeenCalled();

            jasmine.Ajax.requests.mostRecent().response({

                "status": 200,

                "contentType": 'text/plain',

                "responseText": 'awesome response'
            });

            expect(doneFn).toHaveBeenCalledWith('awesome response');
        });

        it("allows responses to be setup ahead of time", function() {
            var doneFn = jasmine.createSpy("success");

            jasmine.Ajax.stubRequest('/another/url').andReturn({
                "responseText": 'immediate response'
            });

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(arguments) {
                if (this.readyState == this.DONE) {
                    doneFn(this.responseText);
                }
            };

            xhr.open("GET", "/another/url");
            xhr.send();

            expect(doneFn).toHaveBeenCalledWith('immediate response')
        });
    });

    it("allows use in a single spec", function() {
        var doneFn = jasmine.createSpy('success');
        jasmine.Ajax.withMock(function() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(arguments) {
                if (this.readyState == this.DONE) {
                    doneFn(this.responseText);
                }
            };

            xhr.open("GET", "/some/cool/url");
            xhr.send();

            expect(doneFn).not.toHaveBeenCalled();

            jasmine.Ajax.requests.mostRecent().response({
                "status": 200,
                "responseText": 'in spec response'
            });

            expect(doneFn).toHaveBeenCalledWith('in spec response');
        });
    });
});

在线演示



标签: , ,

  1. 嗨,你好,看了你的文章受益很多,有个问题想请教一下:关于异步测试,那个ajax的插件看了官网上的解释需要在一个.yml文件中指定加载,但是实际应用中,我这边又需要jasmine与require.js的结合,你看关于用jasmine测试require.js 和ajax 的这三种结合能不能写个相关介绍什么的[爱你],关于这方面的资料实在少的可怜。。

  2. 你好,学习这个框架进行异步测试的时候运行失败,输出: jasmine.Ajax.requests.mostRecent().response({}); 不是一个构造函数,请问这个是什么情况撒? 是不是没引用对jasmine-ajax.js的原因?

  3. 一年前的文章了,说实话早忘了,而且jasmine应该已经升级过很多版本了,把我这些文章看了,再去看官方文档,应该还是挺容易的。官方,github或者stackoverflow应该有基于amd的测试方法。

  4. 少引用? 去官网看了 理解的意思应该是只需要jasmine-ajax.js吧 ,而且jasmine.Ajax.install(); 这一句好使,应该是引用正确了哇。。搞不懂

无觅相关文章插件,快速提升流量