如何延迟 Sinon JS 中假后端的特定响应

How to delaying specific response from fake backend in Sinon JS

在我的应用程序中,我使用 - Backbone 框架。 Karma、Jasmine、SinonJS - 用于测试。

我有简单的 Backbone 视图,像这样:

View = Backbone.View.extend({
    el: ‘#app’,
    initialize: function () {
        var collection1 = new Collection1();// creates collection which can receive data from backend
        var collection2 = new Collection2(); // another one

        collection1.fetch().done(function() { // backbone sends the request for data to backend
            //render data1 which received from backend and append to el
        });
        collection2.fetch().done(function() {
            //render data2 which received from backend and append to el
        });
    }
});

两个集合发送不同的请求(不同的 url)。

我需要测试这段代码,我需要在 collection2 将 return 来自 collection1 之后的后端数据的情况下创建。这种情况需要得到保证。这是本次测试的主要思路。

我知道如何延迟对假后端的所有请求,但我不明白如何延迟其中一个请求。

我使用此 JSFiddle

中的异步测试

我的测试代码:

define(function(require) {

    //get all dependencies

    function testAsync(delayTime) { // make delay
        var deferred = $.Deferred();
        setTimeout(function() {
            deferred.resolve();
        }, delayTime);
        return deferred.promise();
    }
    describe('test ', function() {
        var view = null,
            server = null;

        beforeEach(function(done) {
            server = sinon.fakeServer.create(); // fake sinon server
            server.autoRespond = true;          // enable autoanswer

        testAsync(3000)                     // delay 3 sec
        .done(function(done) {
                server.respondWith('GET', urlsForRequest.collection1, [
                    200,
                    {"Content-Type": "application/json"},
                    mockData1]);
                server.respondWith('GET', urlsForRequest.collection2, [
                    200,
                    {"Content-Type": "application/json"},
                    mockData2]);
                done(); // all is good go to it section, it's a jasmine func
            });

            view = new View(); // create Backbone View

        });

        afterEach(function() {
            server.restore();
        });

        it('can be instantiated', function() {
            // in this section need to use expect
        });

    });
});

此测试延迟了所有响应,但我只需要延迟一个。

我怎样才能更改此代码,以便实施测试正确?

PS。对于 T.J。 我尝试使用此代码,结果相同

server.respondWith('GET', urlsForRequest.collection2, function(fakeRequest) {
    fakeRequest.autoRespond = true;
    fakeRequest.autoRespondAfter = 3000;
    fakeRequest.respond(200, {"Content-Type": "application/json"}, mockData2);
    done();
});

在这种情况下,您不应设置 server.autoRespond = true;。此外,您不需要 testAsync 函数,因为 sinon 已为其内置选项,如果有必要:server.autoRespondAfter.

先回复你想成功的请求,

server.respondWith('GET', urlsForRequest.collection1, [
                200,
                {"Content-Type": "application/json"},
                mockData1]);

然后响应第二个请求,也许将其包装在超时中以确保它在前一个请求之后添加到队列中:

setTimeout(function(){
 server.respondWith('GET', urlsForRequest.collection2, [
                200,
                {"Content-Type": "application/json"},
                mockData2]);
}, 0);

如果由于某种原因最后不起作用,您有:

boolean request.async

Whether or not the request is asynchronous.

为了测试的目的,你可以让它们同步,以确保一个接一个地完成。

好的,这就是我的解决方案。

首先,我禁用了所有 autoRespond 选项并删除了 server.respond() 以进行手动回复。

下一步调试后我在假服务器选项中找到 - queue。如果您有很多请求,此队列包含所有对假服务器的假请求的数组。存在特殊选项(firstRequestsecondRequestthirdRequestlastRequest)。每个 fakeRequest 都有方法 respond(code, contentType-Object, body),您可以使用它手动发送特定请求的响应。

所以我的测试代码在所有更改后都是这样实现的:

define(function(require) {

    //get all dependencies

    describe('test ', function() {
        var view = null,
            server = null;

        beforeAll(function(done) {              // need to save view beetwen requests, change to beforeAll
            server = sinon.fakeServer.create(); // fake sinon server
            view = new View();                  // create Backbone View
            done();                             // run this jasmine-method to say jasmine - "All is good, run immediately tests in it-sections"

        });

        afterAll(function() {
            server.restore();
            view = null;
        });

        it('run response for second request by firstly', function() {
            server.secondRequest.respond(200,
                {"Content-Type": "application/json"},
                mockData2);
            // in this section need to use expect and check state of view
        });
        it('run response for first request by secondly', function() {
            server.firstRequest.respond(200,
                {"Content-Type": "application/json"},
                mockData1);
            // in this section need to use expect and check state of view
        });

    });
});

我的开发部门:

"devDependencies": {
    "jasmine-core": "^2.6.4",
    "karma": "^1.7.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-jasmine": "^1.1.0",
    "karma-phantomjs-launcher": "^1.0.4",
    "karma-requirejs": "^1.1.0",
    "karma-sinon": "^1.0.5",
    "sinon": "^2.3.6"
  }