Сбой ajax модульного теста с Q-Unit

Я использую jQuery $.when для обработки обратных вызовов ajax и использую mockjax для моделирования различных ответов в моих модульных тестах. Один из ответов возвращает ошибку состояния 500. Мой обратный вызов сбоя выдает ошибку, и в Q-Unit я пытаюсь поймать эту ошибку, используя «повышения», но все, что я получаю, это фактическая ошибка.

Вот код:

var bar = new Object();  
// ajax call, returns a promise object 
bar.ajaxCall = function () {  
  return $.ajax({
      url: "foo/foo"
      , dataType: "json"
      , data: { "blah": "blee" }    
  }); 
}

// function I'm testing ...
bar.handleAjax = function () {
    return $.when(ajaxCall.call(this))
      .done(function(data) { /* Success callback */ })
      .fail( throw "Error!!"; });
}

Модульный тест:

// Mock ajax call in the unit test
var mock = $.mockjax({
   url: "foo/foo"
   , contentType: "json"
   , status: 500
});

// unit test for "load"
loadTest = function () {
   test("testing load failure", function () {
      stop(); // stop the test so QUnit knows to wait for the ajax response
      raises(function () {
         var promise = bar.handleAjax();
      }, "We expect an error to be thrown");
      setTimeout(function() { 
         start();
      }, 500);
   });
}

Как я могу переписать тест, чтобы убедиться, что handleAjax выдает ошибку в нужное время?


person stinkycheeseman    schedule 12.12.2011    source источник


Ответы (1)


Проблема в том, что вызов handleAjax() внутри raises() немедленно завершится, и ошибка будет выброшена вне этой функции.

Чтобы решить эту проблему, вы можете сделать вызов ajax синхронным, и таким образом ошибка будет выброшена внутри raises().

raises(function () {
  $.ajaxSetup({ async: false });
  bar.handleAjax();
}, "We expect an error to be thrown");

ЗДЕСЬ — рабочий код.

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

bar.handleAjax = function(success, error) {
  return $.when(this.ajaxCall.call(this))
    .done(function() { success && success.call(this); })
    .fail(function() { error && error.call(this); });
};

ЗДЕСЬ является примером.

Ждем лучших идей :).

person kubetz    schedule 12.12.2011
comment
Большое спасибо @dzejkej. Есть ли причина не запускать все ajax синхронно в модульных тестах? Кажется, что было бы проще писать тесты, поскольку вам не нужно было бы устанавливать тайм-ауты всякий раз, когда вам приходилось ждать выполнения операций. Хотя это также не поможет вам обнаружить условия гонки. Второе решение работает для меня, я думаю, что так будет чище. - person stinkycheeseman; 13.12.2011
comment
@stinkycheeseman: у меня нет проблем с синхронным запуском ajax в тестах, поскольку это упрощает реализацию. Но некоторые люди автоматически злятся, когда видят комбинацию async: false и $.ajax :P. Я не вижу другого решения без изменения реализации bar. - person kubetz; 13.12.2011