【问题标题】:How can I write a test for $cookieStore like this?我怎样才能像这样为 $cookieStore 编写测试?
【发布时间】:2015-11-17 07:38:56
【问题描述】:

我有两个角色:一个是管理员,另一个是普通用户。管理员可以导航到项目详细信息页面,而普通用户不能。因此,我在用户登录时将用户的角色存储在“全局”cookie 中。我从 cookieStore 获取他们的角色,以检查哪个可以导航到项目详细信息页面。这个功能很好用。但是,我不知道如何在 checkUserRole 函数中为 $cookieStore 编写测试:

angular.module('config', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider) 
{
    $urlRouterProvider.otherwise('/login');
    $stateProvider
    .state('login', 
    {
        url: '/login',
        templateUrl: 'login-page.html',
        controller: 'LoginController'
    })
    .state('index',
    {
        url: '/index',
        templateUrl: 'bridge.html'
    })
    .state('item-detail',
    {
        url: '/index/item-detail/:Name',
        templateUrl: 'item-detail.html',
        controller: 'myCtrl',
        resolve:
        {
            checkUserRole: function($cookieStore)
            {
                if($cookieStore.get('globals').currentUser.userRole === 'user')
                {
                    return state.go('index');
                }
            }
        }
    });
});

还有,这是我的测试用例:

describe('config', function()
{
    var $scope, $state, $cookieStore, userRole;
    beforeEach(function()
    {
        module('config', function($provide)
        {
            $provide.value('$cookieStore', { get: 'globals' });
        });
        inject(function($injector, $templateCache)
        {
            $scope = $injector.get('$rootScope');
            $state = $injector.get('$state');
            $cookieStore = $injector.get('$cookieStore');
            $templateCache.put('login-page.html', '');
            $templateCache.put('bridge.html', '');
            $templateCache.put('item-detail.html', '');
        });
    });
    it('home page', function()
    {
        $scope.$apply();
        expect($state.current.name).toBe('login');
        expect($state.current.templateUrl).toBe('login-page.html');
        expect($state.current.controller).toBe('LoginController');
    });
    it('login page', function()
    {
        $scope.$apply(function()
        {
            $state.go('login');         
        });
        expect($state.current.name).toBe('login');
        expect($state.current.templateUrl).toBe('login-page.html');
        expect($state.current.controller).toBe('LoginController');
    });
    it('items page', function()
    {
        $scope.$apply(function()
        {
            $state.go('index');         
        });
        expect($state.current.name).toBe('index');
        expect($state.current.templateUrl).toBe('bridge.html');
    });
    it('item-detail page', function()
    {
        spyOn($cookieStore, 'get').and.callFake(function()
        {
            return 'user';
        });
        expect($cookieStore.get('globals')).toBe('user');
        $scope.$apply(function()
        {
            $state.go('item-detail');
        });
        expect($state.current.name).toBe('item-detail');
        expect($state.current.templateUrl).toBe('item-detail.html');
        expect($state.current.controller).toBe('myCtrl');
        expect($state.href('item-detail', { Name: 'lumia-950'})).toEqual('#/index/item-detail/lumia-950');
    });
});

我的问题是:如何为$cookieStore.get('globals').currentUser.userRole 编写测试?或者我如何模拟它来测试用户的角色是否是用户?。

【问题讨论】:

    标签: angularjs unit-testing jasmine angular-mock


    【解决方案1】:

    我不知道您使用的是哪个版本的 Angular,但 $cookieStore 现在已弃用,更喜欢使用 $cookies 代替 (see doc)。

    至少有 3 种方法可以继续:

    在 Angular 中使用 Jasmine $cookie(来自 v1.4.x):

    describe('config module', function(){
        var $cookies;
    
        beforeEach(function(){
            angular.mock.module('config');
            angular.mock.inject(function(_$cookies_){
                $cookies  = _$cookies_;
            });
        });
    
        it('should have a "globals" cookie with "user" value', function(){
            var globals = $cookies.getObject('globals');
    
            expect(globals.currentUser.userRole).toBe('user');
        });
    });
    

    Jasmine 与纯 JavaScript 结合使用

    describe('config module', function(){
        it('should have a "globals" cookie with "user" value', function(){
            var globals = document.cookie.replace(/(?:(?:^|.*;\s*)globals\s*\=\s*([^;]*).*$)|^.*$/, "$1");
            globals = JSON.parse(globals);
    
            expect(globals.currentUser.userRole).toBe('user');
        });
    });
    

    使用 Jasmine 和量角器(e2e 测试):

    describe('config module', function(){
        it('should have a "globals" cookie with "user" value', function(){
            var globals = JSON.parse(browser.manage().getCookie('globals'));
            expect(globals.currentUser.userRole).toBe('user');
        });
    });
    

    这里 Protractor 给了我们browser 全局变量来处理浏览器相关的行为。

    请注意,JSON.parse() 用于反序列化 cookie 字符串值并将其解析为可用的 JavaScript 对象。

    例子:

    var obj = JSON.parse('{ "foo" : "bar" }');
    console.log(obj.foo);    //print 'bar' in the console
    

    重要提示:

    在您的应用程序中,仅使用 Angular 1.4.7 版本的 Angular 库和 Angular 1.4.7 核心。

    如果有帮助,请告诉我。

    【讨论】:

    • 感谢您的宝贵时间。我真的很适合你的帮助。你能为我解释更多关于JSON.parse(browser.manage(). )的信息吗?因为 Jasmine 警告“浏览器未在文件中定义”。我对 angularJS 使用 1.4.7 版,对 angularJS cookie 使用 1.5.0-beta.1 版
    • 我已经更新了帖子,为您提供更多详细信息。请看一下,如果您需要更多信息,请告诉我
    • 抱歉,还是不行。我还需要添加更多内容吗?因为 Jasmine 警告说“unpr?p0=%24cookiesProvider%20%3C-%20%24cookies”
    • 您必须加载 angular、angular-cookies 和 angular-mocks 库才能使测试正常工作。请检查它们是否正确加载。
    • 非常感谢。我明白了你的想法。
    猜你喜欢
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 2014-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多