简体   繁体   English

如何使用jasmine模拟XHR中的超时事件?

[英]How can I simulate a timeout event in a XHR using jasmine?

I'm testing a function that makes AJAX requests, allowing retries when the network is not working or there are timeouts because the connection is unstable (I'm thinking about mobile devices). 我正在测试一个发出AJAX请求的函数,允许在网络不工作时重试,或者由于连接不稳定而导致超时(我正在考虑移动设备)。

I'm sure it works because I've used it integrated with other code, but I want to have a proper test. 我确定它有效,因为我已将它与其他代码集成使用,但我希望进行适当的测试。

However I haven't been able to create a unit test to ensure it formally. 但是,我无法创建单元测试来正式确保它。 I'm using jasmine 2.3 along with karma and here is my code so far: 我正在使用茉莉花2.3和业力,这是我的代码到目前为止:

var RETRIES=2;
var TIMEOUT=1000;

function doRequest(method, url, successFn, errorFn, body, retries) {
    var request = new XMLHttpRequest();
    retries = retries === undefined ? RETRIES : retries;
    request.open(method, url);
    request.setRequestHeader('Accept', 'application/json');
    request.setRequestHeader('Content-Type', 'application/json');

    request.onload = function () {
        if (request.status < 300 && request.status >= 200) {
            successFn(JSON.parse(request.responseText));
        } else {
            if (errorFn) {
                errorFn(this.status, this.responseText);
            }
        }
    };
    request.onerror = function () {
        if (this.readyState === 4 && this.status === 0) {
        //there is no connection
            errorFn('NO_NETWORK'); 
        } else {
            errorFn(this.status, this.responseText);
        }
    };

    if (retries > 0) {
        request.ontimeout = function () {
            doRequest(method, url, successFn, errorFn, body, retries - 1);
        };
    } else {
        request.ontimeout = function () {
            errorFn('timeout');
        };
    }
    request.timeout = TIMEOUT;
    if (body) {
        request.send(body);
    } else {
        request.send();
    }
}

And this is my test: 这是我的考验:

describe('Ajax request', function () {
    'use strict';

    var RETRIES=2;
    var TIMEOUT=1000;

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

    });

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


    it(' should call error callback function when a tiemout happens', function () {
        var doneFn = jasmine.createSpy('onLoad');
        var errorFn=jasmine.createSpy('onTimeout');
        doRequest('GET','http://www.mockedaddress.com', doneFn, errorFn,null,RETRIES);
        var request = jasmine.Ajax.requests.mostRecent();

        expect(request.method).toBe('GET');
        jasmine.clock().tick(TIMEOUT*(RETRIES+1)+50); //first attempt and then 2 retries
        expect(errorFn).toHaveBeenCalled(); // assertion failed
    });

});

And this is the output of the test: 这是测试的输出:

    Expected spy onTimeout to have been called.
        at Object.<anonymous> (js/test/doRequest_test.js:75:0)
Chrome 42.0.2311 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.007 secs / 0.008 secs)

Use .responseTimeout on a mocked request object, this method is provided by jasmine-ajax , but is not documented. .responseTimeout的请求对象上使用.responseTimeout ,此方法由jasmine-ajax提供 ,但未记录。

jasmine.Ajax.requests.mostRecent().responseTimeout();

But after that, calling .responseTimeout on the first request, you still have an error, because the errorFn callback fires only after several retries. 但是在那之后,在第一个请求上调用.responseTimeout ,你仍然有一个错误,因为只有在几次重试后errorFn触发errorFn回调。 You have to deal with the next requests which are being sent automatically by request.ontimeout defined in your code. 您必须处理由代码中定义的request.ontimeout自动发送的下一个请求。 It can be solved like that: 可以这样解决:

var retries = 3;
var request;

do {
  request = jasmine.Ajax.requests.mostRecent();

  request.responseTimeout();

  retries -= 1;

} while(retries >= 0);

As a result, it will call a timeout for each subsequent request. 结果,它将为每个后续请求调用timeout

Here is some sandbox to play with the code http://plnkr.co/edit/vD2N66EwkpgiLFpg1Afc?p=preview 这里有一些沙盒可以使用代码http://plnkr.co/edit/vD2N66EwkpgiLFpg1Afc?p=preview

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM