У меня есть функция javascript с использованием jquery:

my.namespace.loadSomeStuff = function() {

    $.get('/Services/loadStuff', function(c){
        $("#stuffDiv").html(c);
    });
};

И я пытаюсь написать для этого модульные тесты.

Теперь, поскольку эта функция на самом деле ничего не возвращает и загружает некоторые вещи асинхронно с использованием jquery get, мне трудно это проверить.

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

my.namespace.loadSomeStuff(function(){
    alert('boo');
    assertSame('Login', $("#stuffDiv").find(......);
});

Теперь я создал в шаблоне объект, который вызывает модульный тест, и он будет загружаться и отображаться правильно, но предупреждение или утверждение никогда не выполняются.

Есть ли способ сделать это, не добавляя тонны дополнительного кода к каждой отдельной функции, которая у меня есть?

Спасибо т

1
thorsten codeho 6 Июл 2010 в 14:45

2 ответа

Лучший ответ

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

my.namespace.loadSomeStuff= function(callback) {
    $.get('/Services/loadStuff', function(c){
        $("#stuffDiv").html(c);
        if (callback!==undefined)
            callback();
    });
};

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

Альтернативой было бы использование в тесте грубого тайм-аута.

Вы можете использовать ajaxSuccess, как упомянул Ник (может быть, в сочетании с тайм-аутом и / или также для перехвата ajaxError?). Но мне кажется, что это может добавить слишком много знаний о реализации для модульного теста. Что, если loadSomeStuff в будущем будет изменен для работы без XMLHttpRequest, или, возможно, будет использовать его только иногда, когда он не кэширован? Тогда юнит-тест сломается. Конечно, вы можете обновить тест, чтобы он соответствовал реализации, но тогда это не совсем полезный модульный тест, не так ли?

1
bobince 6 Июл 2010 в 13:25

Для этого вы можете использовать глобальные события AJAX, например:

$(document).ajaxSuccess(function() {
  assertSame('Login', $("#stuffDiv").find(......));
});

ajaxSuccess произойдет после каждого запроса AJAX, если вы хотите, чтобы событие выполнялось после завершения всех одновременных запросов, тогда ajaxStop - это то, что вы ' повторно после. Оба этих обработчика необязательно прикреплять к вашим методам AJAX. напрямую, они могут быть выполнены в модульных тестах.

Это обычные события (полный список здесь), поэтому вы можете .bind() / .unbind() по мере необходимости, например, когда завершен описанный выше модульный тест:

$(document).ajaxSuccess(function() {
  assertSame('Login', $("#stuffDiv").find(......));
  $(this).unbind('ajaxSuccess'); //cleanup
});
1
Benjamin 7 Дек 2013 в 19:23