Angularjs: имитация location.path() с помощью spyOn для модульного теста

Я уже прочитал этот сообщение (и другие), но мне не удается заставить этот простой модульный тест работать. Я использую версию 2 Jasmine. Моя фабрика очень проста:

angular.module('myApp')
    .factory('detectPath', function ($location, $rootScope) {
        'use strict';
        var locationPath = $location.path()
        function getPath () {
            if (locationPath === '/') {
                locationPath = 'home';
            } else {
                locationPath = '';
            }
            $rootScope.path = locationPath;
        }
        getPath();
        return locationPath;
    });

И мой модульный тест такой же простой:

'use strict';
describe('Factory: detectPath', function () {
    var detectPath, $rootScope, $location;

    beforeEach(module('myApp'));
    beforeEach(inject(function (_detectPath_, _$rootScope_, _$location_) {
        detectPath = _detectPath_;
        $rootScope = _$rootScope_;
        $location = _$location_;
        spyOn($location, 'path').and.returnValue('/');
    }));

    it('should return pathName', function ($location) {
        expect($rootScope.path).toBe('home');
    });
});

Это не проходит тест (я получаю сообщение об ошибке, ожидая, что false будет «домом»).

Что я делаю неправильно? Есть ли способ проверить, что spyOn был вызван (только один раз)?


person Simon    schedule 01.05.2015    source источник


Ответы (1)


В вашем коде есть две основные проблемы.

Прежде всего, ваша функция getPath() выполняется до того, как вы настроите spy. Вы должны либо установить шпиона в предыдущем beforeEach, либо ввести свою фабрику в тесте (я выбрал второе решение).

Вторая проблема (которая пока не влияет на тест) заключается в том, что вы скрываете свою переменную $location с аргументом функции теста - вы не сможете получить к ней доступ, так как она всегда будет неопределенной. После того, как я удалил этот аргумент, я могу проверить, был ли вызван шпион с помощью expect(...).toHaveBeenCalled().

Вот рабочий код:

describe('Factory: detectPath', function () {
    var detectPath, $rootScope, $location;

    beforeEach(module('myApp'));
    beforeEach(inject(function (_$rootScope_, _$location_) {
        $rootScope = _$rootScope_;
        $location = _$location_;
        spyOn($location, 'path').and.returnValue('/');
    }));

    it('should return pathName', function () {
        inject(function (detectPath) {
            expect($location.path).toHaveBeenCalled();
            expect($rootScope.path).toBe('home');
        });
    });
});

И JSFiddle (с использованием Jasmine 1.3, но единственная разница в этом примере заключается в том, что вы вызываете and.returnValue в Jasmine 2 и returnValue в Jasmine 1.3).

person fracz    schedule 02.05.2015