Как написать модульный тест для встраивания запросов ajax?

У меня есть метод handleDownload, который запускает загрузку файла. Функция отправляет на серверную часть, которая возвращает ответ, основанный на том, что новый запрос отправляется на сервер, где находятся файлы. Я увидел, что могу использовать mockjax для имитации запросов, но как обрабатывать разные пути, такие как успех , ошибка и т. д. Как мне узнать, какой ответ запускает какой путь (успех, ошибка, завершение, ...). Что было бы отличной стратегией для тестирования функции handleDownload и как? Для насмешек я использую Sinon.js У меня пока нет глубокого понимания. Я также должен проверить, вызывается ли функция handleDownloadFinal.

handleDownload: function(data, url) {
$.ajax({
    type: "POST",
    url: url,
    data: {},
    success: function(response) {
        if (response.success) {
            var start_token = response.token;
            $.ajax({
                type: start_token.method,
                url: start_token.url,
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('Authorization', start_token.header);
                },
                success: function(start_response) {
                    handleDownloadFinal(start_response.status_token);
                },
                error: function(start_response) {
                    $.ajax({
                        type: "POST",
                        url: url + 'proxy/',
                        success: function(fallback_response) {
                            if (fallback_response.success) {
                                handleDownloadFinal(fallback_response.status_token, true, fallback_response.job_uuid);
                            } else {
                                errorDownload(response.error);
                            }
                        },
                        error: function(fallback_response) {
                            // Now this is some real error                                    
                            generalErrorDownload();
                        },
                        dataType: 'json'
                    });
                },
                dataType: 'json',
                xhrFields: {
                    withCredentials: true
                }
            });
        } else {
            errorDownload(response.error);
        }
    },
    error: function(response) {
        generalErrorDownload();
    },
    complete: function() {
    },
    dataType: "json"
});

}

person Balázs Szántó    schedule 15.08.2013    source источник


Ответы (1)


Вам следует использовать поддельный сервер, поставляемый с sinon.

before(function(){
    //create the server 
    this.server = sinon.fakeServer.create();
    // let the server automatically respond for every request
    server.autoRespond = true;
})

it('test something', function(){

    //let the server respond for  specific url with 200-ok
    this.server.respondWith("POST", "/some/article/comments.json", [200, {
      "Content-Type": "application/json"
    }, '[{ "id": 12, "comment": "Hey there" }]']);
})

Поскольку у вас есть куча запросов, и вам нужно проверить все комбинации, я бы предложил иметь вспомогательную функцию для каждого успешного завершения запроса, чтобы вы могли протестировать такие случаи:

function letFirstRequestSucceed() {
  this.server.respondWith("POST", "urlForFirstRequest", [200, {
    "Content-Type": "application/json"
  }, '[{ "id": 12, "comment": "Hey there" }]']);
}


function letSecondRequestFail() {
  this.server.respondWith("POST", "urlForSecondRequest", [404, {
    "Content-Type": "application/json"
  }, '{error: "some error message"}');
}


function letThirdRequestFail() {
  this.server.respondWith("POST", "urlForThirdRequest", [404, {
    "Content-Type": "application/json"
  }, '{error: "some error message"}');
}

it("should to something when the second and third request fails", function () {
  sinon.spy(window, 'generalErrorDownload');
  letFirstRequestSucceed();
  letSecondRequestFail();
  letThirdRequestFail();

  handleDownload('someDate', 'aUrl');

  expect(generalErrorDownload)

})

Кстати, вам следует подумать о рефакторинге кода с использованием jquerys deferred, который поддерживается API ajax. вызовы, это сделало бы ваш запрос гораздо более читабельным.

person Andreas Köberle    schedule 15.08.2013
comment
Когда я имитирую вещи и использую fakeServer, все будет работать синхронно, верно? - person Balázs Szántó; 16.08.2013
comment
да, поддельный сервер немедленно вызовет сообщение об успехе/ошибке. - person Andreas Köberle; 16.08.2013
comment
Вы должны вызвать server.respond(), чтобы указать серверу вернуться из запросов AJAX, обычно непосредственно перед выполнением тестовых утверждений. Вы можете включить синхронный режим с помощью server.autoRespond = true, хотя я этого не пробовал. - person David Harkness; 10.10.2013