Angular JS-тестирование функции с редиректом страницы с использованием Karma / Jasmine


У меня есть функция в моем угловом контроллере, которая выглядит следующим образом:

$scope.myFunction = function(){
    $scope.myVariable = "something";
    $scope.myOtherVariable = "something else";
    window.location.href = "/path/to/page"; 
}

Простой тест жасмина охватывает вышеуказанную функцию и выглядит следующим образом:

describe('my test', function(){
    it('should pass', function(){
        scope.myFunction();
        expect(scope.myVariable).toBe('something');
        expect(scope.myOtherVariable).toBe('something else');     
    });
});

Вышеописанный тест сам проходит, но затем карма выбрасывает в консоль следующую ошибку:

Некоторые из ваших тестов сделали полную перезагрузку страницы!

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

Я подумал о том, чтобы дать оба анонимных функции в тесте Jasmine и угловые имена, а затем с помощью arguements.callee.caller.name внутри исходной функции, чтобы определить, вызывается ли функция сама по себе или жасмин. К сожалению, arguments.callee.caller.name всегда возвращает undefined, что, как я подозреваю, вызвано тем, как Angular и Jasmine связаны друг с другом.

2 7

2 ответа:

Уже давно этот вопрос не задавался, но следующий подход должен быть чище:

Изменив исходную функцию на использование сервиса $window от Angular вместо объекта browser window, можно написать тест, который не требует изменения производственного кода или учета каких-либо параметров среды выполнения. Это, конечно, требует, чтобы $window была зависимостью для контроллера, в котором находится функция.

Используя angular-mocks/ngMock , что-то например:

var fakeWindow = {
  location: {
    href: ''
  }
}
// instantiate controller with mock window
beforeEach(inject(function($controller) {
  $controller('YourCtrlName', {
    $window: fakeWindow
  });
}));

Должен позволить тесту Пройти, предполагая, что контроллеру не нужно $window ни для чего другого.

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

$scope.Navigate = function() {
    window.location.href = "/path/to/page";
};

Или даже лучше в какой-то службе

app.factory('navigator', function() {
    return {
        Navigate: function(path) {
            window.location.href = path;
        }
    };
});

Затем в своем тесте вы можете использовать шпиона для навигации, чтобы убедиться, что навигация была вызвана, но на самом деле не вызывайте навигацию.