Подтвердить что ты не робот

Можно ли высмеять объект window.location для теста qUnit?

Скажем, у меня есть функция полезности, которая для простоты (реальная вещь сложна и неактуальна) возвращает текущую оконную последовательность.

var someUtilityFunction = () {
    return window.location.search.substring(1);
};

Теперь я хочу unit test эту функцию в qUnit (не уверен, что тестовый жгут имеет отношение или нет):

test('#1 someUtilityFunction works', function () {
    // setup
    var oldQS = window.location.search;
    window.location.search = '?key1=value1&key2=value2&key3=value3';

    var expectedOutput = 'key1=value1&key2=value2&key3=value3';

    // test
    equals(someUtilityFunction(),
        expectedOutput,
        'someUtilityFunction works as expected.');

    // teardown
    window.location.search = oldQS;
});

Проблема заключается в том, что установка window.location.search в другую цепочку вызывает перезагрузку страницы, по сути входя в бесконечный цикл запроса. Есть ли способ вычеркнуть объект window.location без внесения каких-либо изменений в функцию someUtilityFunction?

4b9b3361

Ответ 1

Мы столкнулись с той же проблемой несколько дней назад. В основном существует 2 подхода:

Перепишите свой код

Это может быть не самое лучшее (если есть) решение, но подумайте о передаче объекта window в свою функцию, чтобы сделать насмешливым. Еще лучше, используйте закрытие и инкапсулируйте свой код. Это имеет еще несколько преимуществ:

  • Вы можете затенять глобальные vars
  • Вы можете использовать частные локальные vars
  • Вы можете избежать коллизий имен.
  • Затенение делает насмешливым очень легко, просто передайте что-то еще.

Оберните свой код

Вы можете обернуть весь свой код внутри функции, которая превращает объект окна в локальную переменную. У вас есть в основном две возможности:

Предположим, что это макет:

var customWindow = {
    location: {
        search: "",
        hash: ""
    }
};

Используйте закрытие

var someUtilityFunction;

(function(window) {
    // window is now shadowed by your local variable
    someUtilityFunction = () {
        return window.location.search.substring(1);
    };
})(customWindow);

Это тень глобального window с локальным window.

Используйте оператор with

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

// first some more preparation for our mock
customWindow.window = customWindow;

with(customWindow) {

    // this still creates the var in the global scope
    var someUtilityFunction = () {
        // window is a property of customWindow
        return window.location.search.substring(1);
    };

    // since customWindow is our scope now
    // this will work also
    someUtilityFunction = () {
        // location is a property of customWindow too
        return location.search.substring(1);
    };

}
Кстати, я не знаю, имеет ли свойство search те же симптомы, что и свойство hash, а именно, иногда включает знак вопроса, а иногда и нет. Но вы можете рассмотреть возможность использования
window.location.search.replace(/^\?/, "");

вместо

window.location.substr(1);

Ответ 2

У меня был некоторый успех, используя window.history.pushState. См. fooobar.com/info/674/.... Для каждого unit test я вызываю функцию setQueryString('var=something'), которую затем реализую следующим образом:

function setQueryString(queryString) {
  window.history.pushState({}, '', '?' + queryString);
}

Вам нужно очистить строку запроса с помощью метода afterEach метода QUnit.module, иначе строка запроса будет установлена ​​на значение окончательного теста, и вы получите странные результаты.