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

Javascript 如何在Sinon JS中延迟假后端的特定响应,javascript,jquery,backbone.js,jasmine,sinon,Javascript,Jquery,Backbone.js,Jasmine,Sinon,在我的应用程序中,我使用主干框架。Karma,Jasmine,SinonJS-用于测试 我有一个简单的主干视图,如下所示: View = Backbone.View.extend({ el: ‘#app’, initialize: function () { var collection1 = new Collection1();// creates collection which can receive data from backend va

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

我有一个简单的主干视图,如下所示:

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
        });
    }
});
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
        });

    });
});
两个集合发送不同的请求(不同的URL)

我需要测试这段代码,我需要确定collection2将在collection1之后从后端返回数据的情况。这种情况需要得到保证。这是这次测试的主要内容

我知道如何延迟所有伪造后端的请求,但我不知道如何延迟其中一个请求

我使用异步测试

我的测试代码:

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
        });

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

如何更改此代码以实现正确的测试

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.autorespondeafter

只要回应你想先成功的请求

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);
如果由于某种原因,这不起作用,那么最终您必须:

布尔请求.async

请求是否是异步的

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

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

首先,我禁用了所有
autoRespond
选项,并删除了手动响应的
server.respond()

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

因此,我的测试代码在所有更改实现后如下所示:

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
        });
    }
});
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"
  }

我尝试使用setTimeout,但在它的部分中,我没有collection2的数据。这不是工作。接下来,我尝试在fakeRequest中使用autorespondAfter。结果是一样的。将代码添加到我的主消息中。FakeRequest的async=true选项我在回答中说不要使用
autoRespond
autorespondeafter
,但您正在使用它。它们是服务器的属性,但您正在请求中设置它们,我不知道为什么。我不明白
做了什么()在更新的代码中用于。最后,如果所有其他操作都失败,我提到可以使用
async
选项使请求同步。但您将其设置为
true
,并保持其异步。你正在做一系列的事情,但都做错了,请仔细阅读答案,逐个做,删除我在所有方法中使用的不必要的代码和属性。有、无自动响应自动响应。我过去常常像你说的那样设置超时——这不管用。当我在没有设置超时的情况下运行时。假服务器获取异步应答,但第一个collection1.fetch(10毫秒后)和第二个collection2.fetch(10毫秒后)。10ms-这是异步响应的默认延迟。若我在setTimeout func中运行second responseWith,那个么我只收到来自first的响应,而来自second response的数据并没有预先设置在“it”部分。我在文档中找不到任何文字说明如何实现一个请求的默认延迟(10毫秒),另一个请求的默认延迟为3000毫秒。问题可能是您想到了与真实服务器类似的假服务器,试图按照真实世界中发生的情况执行测试。它是一个伪造服务器,当您告诉它响应时,它只响应匹配的请求。因此,您可以发送请求,告诉服务器响应,发送另一个请求,告诉服务器响应。因此,您可以按照希望的顺序获得请求响应,就这么简单。您可能正在使用与其他测试相同的fakeserver实例,该实例设置为自动响应请求等。在应用程序外部创建一个小测试,测试我上面提到的内容。是的,我考虑过这种方法。但是,在新南威尔士州,如果我理解正确的话。存在两种发送响应的方式。First-config autoRespond=true。发送请求时,默认情况下,fakeServer在10毫秒后发送异步响应。其次,当您使用server.respond()方法手动发送respond时。此方法发送队列中所有请求的响应。我不知道如何手动响应特定请求:(据我所知,
done()
用于处理异步操作,例如在
beforeAll()
中,如果您需要等待请求或在请求完成后调用
done()
,在本例中,因为您没有类似的操作,
done()
是不必要的。顺便说一句,恭喜您找到了解决方案