单元测试UI路由器解析

时间:2016-05-04 09:39:47

标签: angularjs angular-ui-router jasmine karma-runner karma-jasmine

我正在尝试使用ui-router为我的resolve编写单元测试。

Router.js

define(['module', 'require'], function(module, require) {
    'use strict';

    var Router = function ($stateProvider, $urlRouterProvider) {

        $urlRouterProvider.otherwise('/shopping');

        $stateProvider
            .state('shopping', {
                url: '/shopping',
                templateUrl: 'app/shopping.html',
                resolve:{
                    userFactory : 'UserFactory',
                    checkAccess:function(userFactory){
                        return userFactory.checkUser();
                    }
                }
            })
            .state('products', {
                url: '/products',
                templateUrl: 'app/products.html',
                resolve:{
                    userFactory : 'UserFactory',
                    checkAccess:function(userFactory){
                        return userFactory.checkUser();
                    }
                }
            })
            .state('notAuth', {
                url: '/notAuth',
                templateUrl: 'app/unauthorised.html'
            });
    };

    module.exports = ['$stateProvider', '$urlRouterProvider', Router];
});

在userFactory.checkUser()中;我基本上检查用户'权限,并重定向到templateUrl,或执行:

$state.go('notAuth');

我的当前.spec.js:

define(['require', 'angular-mocks', 'angular-ui-router', 'app/router'], function (require) {
    'use strict';
    describe('myApp/myState', function() {

        var $rootScope, $state, $injector, myServiceMock, $httpBackend, state = 'shopping';

        var mockResponse = {
            "access": true
        }

        var angular = require('angular');
        var myRouter = require('app/router');

        beforeEach(module('ui.router'));

        beforeEach(function() {

            module(myRouter, function($provide) {
                $provide.value('userFactory', myServiceMock = {});
            });

            inject(function(_$rootScope_, _$state_, _$injector_, $templateCache, _$httpBackend_) {
                $rootScope = _$rootScope_.$new();
                $state = _$state_;
                $injector = _$injector_;
                $httpBackend = _$httpBackend_;
                $rootScope.$digest();
            })
        });

        it('should transition to shopping', inject(function($state,$rootScope){
            $state.transitionTo('shopping');
            $rootScope.$apply();
            expect($state.current.name).toBe('shopping');
        }));

        it('should resolve data', function() {
            myServiceMock.checkUser = jasmine.createSpy('checkUser').and.returnValue(mockResponse);
            // earlier than jasmine 2.0, replace "and.returnValue" with "andReturn"

            $state.go(state);
            $rootScope.$digest();
            expect($state.current.name).toBe(state);
        });
    });
});

通过上述测试,我收到以下错误:

Information:  myApp/myState
Information:    should transition to shopping   Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Information:    Watchers fired in the last 5 iterations: []
Information:    http://errors.angularjs.org/1.4.0/$rootScope/infdig?p0=10&p1=%5B%5D

Information:    should resolve data Expected '' to be 'shopping'.

1 个答案:

答案 0 :(得分:3)

看起来这里发生了一些事情。首先,你要消化太多次了。那是" 10 $ digest()迭代达到的#34;信息。要解决这个问题,您应该从注入函数的末尾删除$rootScope.$digest()

我认为实际失败的测试部分是因为您未能解决您在路线中配置的checkAccess决心。尝试将$provide.value('checkAccess', function() {return true;});添加到$provide.value设置中。这应该允许checkAccess在你的路线中解决,这将允许路线完成状态转换。

我在这里找到了类似问题的答案:Angular Jasmine UI router inject resolve value into test