2015-02-03 2 views
1

Я использую QUnit вместе с sinon. Как я могу заставить sinon's fakeserver ответить на прикованный ajax вызов, сделанный из того же метода?Sinonjs fakeserver - несколько вызовов ajax

module('demo', { 
    beforeEach: function(){ 
     this.server = sinon.fakeServer.create(); 
    }, 
    afterEach: function(){ 
     this.server.restore(); 
    } 
}); 

test('chained ajax calls', function(assert){ 

    this.server.respondWith('GET', '/foo', [200, 
    { 'Content-Type': 'application/json' }, '{ "foo": 1 }' ]); 

    this.server.respondWith('GET', '/bar', [200, 
    { 'Content-Type': 'application/json' }, '{ "bar": 1 }' ]); 

    var successCount = 0; 

    $.get('/foo', function(data){ 
     successCount++; 
     $.get('/bar', function(){ 
      console.log('bar success'); 
      successCount++; 
     }); 
    }); 

    this.server.respond(); 
    assert.strictEqual(successCount, 2); 
}); 

Моя проблема выше в том, что я получаю только ответ от одного из методов. Возможно ли, что этот fakeserver справляется с этим?

Обновление: Похоже, что добавление еще server.respond() решает проблему. Но должен быть лучший способ, не так ли?

Согласно документации, это звучит как один вызов должен на работу, независимо от АЯКС подсчета вызовов:

server.respond(); Вызывает все асинхронные запросы в очереди, чтобы получить ответ.

Fiddle: http://jsfiddle.net/3qj20r5m/1/

ответ

3

Хм, я думал, что server.repond() должен был сделать это, как хорошо. В любом случае, я обычно настраивал свой поддельный сервер (ы) для автоматического ответа. Если вам не нужно проверять запросы, прежде чем ответить это, кажется, проще:

var server; 
QUnit.module('fake server tests', { 
    beforeEach: function() { 
     server = sinon.fakeServer.create(); 

     // *** it's this option I'm referring to... 
     server.autoRespond = true; 

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

     server.respondWith('GET', '/bar', [200, { 
      'Content-Type': 'application/json', 
      '{ "bar": 1 }' 
     }]); 
    }, 
    afterEach: function() { 
     server.restore(); 
    } 
}); 

QUnit.test('do some ajax', function(assert) { 
    var done = assert.async(); 

    doTwoAjaxCalls(function() { 

     // whatever your assertions are... 
     // (of course, your method would need to perform the callback...) 

     done(); 
    }); 
}); 

UPDATE

Глядя на обновленный код, который мы можем понять, почему вам нужно позвонить respond() дважды: первый вызов, чтобы ответить " выпускает "первоначальный запрос ajax (до /foo) из своей очереди, который затем вызывает первый успешный обратный вызов. В рамках этого обратного вызова вы инициируете второй вызов ajax, который удерживается Синоном, пока вы снова не вызовете respond().

Другими словами, вызов respond() заставит Sinon выпускать все находящиеся в настоящее время аякс-запросы, но в вашем случае задерживается только один. Использование опции autoRespond, о которой я упоминал выше, устраняет эту потребность, поскольку Sinon «отвечает» немедленно, но я считаю, что вам нужно сделать асинхронный тест в этом случае (или, по крайней мере, это лучшая практика).

Удачи вам!

+0

О, я думал, что поддельные звонки выполнялись синхронно, поэтому я не использовал 'assert.async'. Есть ли способ выполнить вызовы синхронно? – filur

+0

Просто для разработки: во всех образцах с одним вызовом ajax кажется, что вы можете дождаться ответа без остановки QUinit (например, http://www.kenpowers.net/blog/advanced-features-in-sinon/) 'Сделать утверждения, опять же, все синхронно. '"). Однако, с вложенными вызовами, как показано выше, кажется, что вы должны сделать QUnit wait. – filur

+0

Я обновил свой пример, чтобы сделать его ближе к моему реальному коду. Звонки фактически вложены. Возможно, это проблема? – filur

3

В документах Sinon указано, что autoRespond не подходит для тестов, так как он будет выполняться асинхронно. По умолчанию это значение равно 10 мс, чего достаточно, чтобы наброситься на следующий кадр исполнения, что может привести к некоторым условиям гонки в тестах. Я обнаружил это, потому что у меня были подобные вложенные вызовы AJAX, которые я хотел протестировать.

Я закончил реализацию объекта respondImmediately на fakeServer, который будет синхронно отвечать на любой запрос. Это только что объединилось в проект несколько недель назад (v1.14.0), но если вы обновляетесь до самой новой версии, вы сможете ее получить. Check out the docs here..

В блоке beforeEach вместо того, чтобы присвоить значение autoRespond значение true, установите для свойства respondImmediately значение true. Затем удалите все вызовы server.respond(), и вы должны быть установлены!

+0

Ох, круто. Большое спасибо за обмен – filur

+0

Хм, я только что протестировал и, похоже, не работает. Что я упустил? http://jsfiddle.net/3qj20r5m/3/ – filur

+0

Ahh, похоже, что это jQuery-ism, который добавляет 0SM 'setTimeout' в обратный вызов. Вот вложенный случай с использованием raw xhr: http://jsfiddle.net/3qj20r5m/5/. Используя jQuery, вы, возможно, не сможете обойти свои асинхронные тесты:/ –

Смежные вопросы