AngularJS、路由解析、位置更改、单元测试、karma-jasmine

AngularJS, route resolve, location change, unit tests, karma-jasmine

在angular中,我写了一个关于所有操作的路由解析,以检查您是否登录

$routeProvider.when('/home', {
    resolve: {
        Authenticated: function($location, AuthAuthenticator, AuthIdentity) {
            return new Promise(function(resolve, reject) {
                AuthAuthenticator.init().then(
                    function( success ) {
                        if (!AuthAuthenticator.isAuthenticated() ) {
                            $location.path("/login");
                            resolve( true );
                        }
                        resolve( false );
                    },
                    function( error ) {
                        reject( error );
                    }
                );
            });
        }
    }
});

如果您没有登录,我们会将您重定向到登录页面。现在我想在我们的 karma-jasmine 单元测试中测试它。但是如果我写测试,location.path 不会改变。

describe('LoginController', function() {
    beforeEach(module('dcApp'));

    beforeEach(function() {
        var _authenticated = false;

        AuthAuthenticatorMock = {
            isAuthenticated: function() {
                return _authenticated
            },

            setAuthenticated: function( authenticated ) {
                _authenticated = authenticated;
            },
        };

        module( function( $provide ) {
            $provide.value('AuthAuthenticator', AuthAuthenticatorMock);
        });
    });

    var $controller;

    beforeEach(inject(function( _$route_, _$location_, _$controller_, _AuthAuthenticator_ ){
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $route = _$route_;
        $location = _$location_;
        $controller = _$controller_;
        AuthAuthenticator = _AuthAuthenticator_;
    }));

    describe('Controller activation', function() {
        it ('redirects to login if user is not yet logged in', function() {
            AuthAuthenticator.setAuthenticated( false );
            var $scope = {};
            var controller = $controller('HomeController', { $scope: $scope });
            expect( $location.path() ).toBe('/login');
        });
    });

});

但结果是:

PhantomJS 2.1.1 (Linux 0.0.0) HomeController Controller activation redirects to login if user is not yet logged in FAILED
Expected '' to be '/login'.

现在我看到了一些关于间谍的文档,但我不知道如何检查这个位置变化。

您可以在每个事件发生后自行调用解析来正确测试。

describe('LoginController', function() {
    beforeEach(module('dcApp'));

    beforeEach(function() {
        var _authenticated = false;

        AuthAuthenticatorMock = {
            isAuthenticated: function() {
                return _authenticated
            },

            setAuthenticated: function( authenticated ) {
                _authenticated = authenticated;
            },
        };

        module( function( $provide ) {
            $provide.value('AuthAuthenticator', AuthAuthenticatorMock);
        });
    });

    beforeEach( function() {
        var _path = '';

        locationMock = {
            path: function( argument ) {
                if (argument) {
                    _path = argument;
                }
                return _path;
            }
        };

        module( function( $provide ) {
            $provide.value('$location', locationMock );
        });
    });

    var $controller;

    beforeEach(inject(function( _$route_, _$location_, _$controller_, _AuthAuthenticator_ ){
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $route = _$route_;
        $location = _$location_;
        $controller = _$controller_;
        AuthAuthenticator = _AuthAuthenticator_;
    }));

    describe('Controller activation', function() {
        it ('redirects to login if user is not yet logged in', function() {
            AuthAuthenticator.setAuthenticated( false );
            var resolveTest = $route.routes['/home'].resolve.Authenticated;
            $injector.invoke( resolveTest );
        // if it's a promise call apply
            $rootScope.$apply();
            expect( $location.path() ).toBe('/login');
        });
    });

});