Stubbing window.location.href с Sinon

Я пытаюсь протестировать некоторый код на стороне клиента, и для этого мне нужно заглушить значение свойства window.location.href с помощью Mocha/Sinon.

То, что я пробовал до сих пор (используя этот пример):

describe('Logger', () => {
    it('should compose a Log', () => {
        var stub = sinon.stub(window.location, 'href', 'http://www.foo.com');
    });
});

В бегуне отображается следующая ошибка:

TypeError: пользовательский заглушка должна быть функцией или дескриптором свойства

Изменение тестового кода на:

describe('Logger', () => {
    it('should compose a Log', () => {
        var stub = sinon.stub(window.location, 'href', {
            value: 'foo'
        });
    });
});

Что дает эта ошибка:

TypeError: Попытка обернуть свойство string href как функцию

Передача функции в качестве третьего аргумента в sinon.stub тоже не работает.

Есть ли способ предоставить фальшивую строку window.location.href, также избегая перенаправления (поскольку я тестирую в браузере)?

Ответ 1

Штыри не могут заменить атрибуты, только функции.

Выброшенная ошибка усиливает это:

TypeError: пользовательский заглушка должна быть функцией или дескриптором свойства

Из документации:

Когда использовать заглушки?

Используйте заглушку, если хотите:

  • Контролируйте поведение методов из теста, чтобы заставить код перейти по определенному пути. Примеры включают принуждение метода к выдаче ошибки для проверки обработки ошибок.

  • Если вы хотите запретить прямой вызов определенного метода (возможно, потому, что он вызывает нежелательное поведение, например XMLHttpRequest или подобное).

http://sinonjs.org/releases/v2.0.0/stubs/


Возможное решение

В то время как многие встроенные объекты могут быть заменены (для тестирования), некоторые не могут. Для этих атрибутов вы можете создавать объекты фасада, которые затем вам нужно использовать в своем коде и быть в состоянии заменить их в тестах.

Например:

var loc = {

    setLocationHref: function(newHref) {
        window.location.href = newHref;
    },

    getLocationHref: function() {
        return window.location.href;
    }

};

Использование:

loc.setLocationHref('http://acme.com');

Затем вы можете в своем тестовом письме

var stub = sinon.stub(loc, 'setLocationHref').returns('http://www.foo.com');

Обратите внимание на цепочку returns(). В вашем коде была еще одна ошибка: третий аргумент должен быть функцией, а не значением для другого типа. Это обратный вызов, а не возвращаемый атрибут.

Посмотрите исходный код stub()

Ответ 2

Используйте window.location.assign(url) вместо перезаписывания значения window.location. Затем вы можете просто заглушить метод assign объекта window.location.

http://www.w3schools.com/jsref/met_loc_assign.asp

Ответ 3

Вам нужно использовать global, чтобы высмеять объект window для вашего теста в beforeEach или it

например.

it('should compose a Log', () => {
   global.window = {
       location: {
           href: {
               value: 'foo'
           }
       }
   }
  //.... call the funciton 
});