Unit Test 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