karma / angularjs如何使用异步服务测试运行块

时间:2014-08-18 13:02:13

标签: angularjs karma-runner karma-jasmine angular-mock

我如何测试:

init.js lama.system module

angular.module('lama.system', [])
   .config(['$httpProvider', function($httpProvider) {
        // Crossdomain requests not allowed if you want do cors request see filter.php 
        $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    }])
    .run(['$rootScope', '$state', '$log', 'Global',function ($rootScope, $state, $log, Global) {
        $rootScope.$state = $state;
        $rootScope.$log = $log;
        $rootScope.global = Global;
    }]);

controllers.js lama.system module

angular.module('lama.system')
    .controller('SystemController', ['$scope',
        function($scope) {
           $scope.test =[];

         }
    ]);

services.js lama.system module

angular.module('lama.system')
    .factory('Menus', ['$http', function($http) {
        return {
            query : function(menus){
                return $http.get('/api/v1/user/menus', {
                    params: {
                        'menus[]': menus
                    }
                });
            }
        }; 
    }]);

system.js路由器

//Setting up route
angular.module('lama.system')
    .config(['$stateProvider', '$urlRouterProvider',
        function($stateProvider, $urlRouterProvider) {
            $urlRouterProvider.otherwise('/');
            $stateProvider              
            .state('home', {
                url: '/',
                templateUrl: 'system/views/home.html',
                controller:'SystemController'
            });
        }
    ]);

init.js喇嘛模块

angular.module('lama', ['ui.router','restangular','lama.system','lama.users'])
    .run(['$rootScope',  'Menus',function ($rootScope, Menus) {
       // Default hard coded menu items for main menu
           var menus = [
            {
                'permission': null,
                'title': 'Home',
                'link': 'home'
            },
            {
                'permission': 'users',
                'title': 'User',
                'link': 'user_actions.list'
            }
            ];

            $rootScope.menus = [];

            function queryMenu(menus) {
                Menus.query(menus).then(
                    function (result) {
                        $rootScope.menus = result.data; 
                    },
                    function (reason) {
                        throw new Error(reason);
                    }
                    );
            }

            // Query server for menus and check permissions
            queryMenu(menus);

           $rootScope.$on('loggedin', function(event,user) {
                console.log('kkk');
                queryMenu(menus);

                $rootScope.global = {
                    user:  user,
                    authenticated: user.groups.length,
                    isAdmin:  user.groups.indexOf('Admins')
                };
            });


    }]);

测试

(function() {
    describe('Unit test: system module', function () {
        describe('SystemController', function () {

            // load the controller's module
            beforeEach(function() {
                module('lama');
                module('stateMock');
            });

            var SystemController,
            $rootScope,
            $scope,
            $httpBackend;

            // Initialize the controller and a mock scope
            beforeEach(inject(function ($controller, _$rootScope_, _$httpBackend_) {
                $rootScope = _$rootScope_;
                $scope = _$rootScope_.$new();
                $httpBackend = _$httpBackend_;
                SystemController = $controller('SystemController', {
                    $scope: $scope
                });
                $httpBackend.when('GET', '/api/v1/user/menus').respond(200,{});
            }));

            it('should attach a list of awesomeThings to the scope', function () {
                expect($scope.test.length).toBe(0);
            });

            it('should expose some global scope', function() {
                expect($rootScope.global).toBeTruthy();
            });
        });

    });
}());

给我:(

grunt test
Running "karma:unit" (karma) task
INFO [karma]: Karma v0.12.21 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
WARN [watcher]: Pattern "/home/whisher/public_html/public/users/tests/unit/**/*.js" does not match any file.
INFO [PhantomJS 1.9.7 (Linux)]: Connected on socket zK1SplAjTHe4x5sAM9ew with id 16331650
WARN [web-server]: 404: /api/v1/user/menus?menus%5B%5D=%7B%22permission%22:null,%22title%22:%22Home%22,%22link%22:%22home%22%7D&menus%5B%5D=%7B%22permission%22:%22users%22,%22title%22:%22User%22,%22link%22:%22user_actions.list%22%7D
WARN [web-server]: 404: /system/views/home.html
ERROR: 'Error: [object Object]
    at http://localhost:9876/base/public/init.js?c7a481724bcf81e4810141349c93d0f698a18904:34
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:100
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:100
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:101
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:112
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:109
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:112
    at h (http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:72)
    at x (http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:77)
    at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:78'
PhantomJS 1.9.7 (Linux): Executed 2 of 2 SUCCESS (0.039 secs / 0.065 secs)

Done, without errors.

NB

我正在使用ui-router

1 个答案:

答案 0 :(得分:1)

我已经查看了您的源代码。主要违规项目是:

angular.element(document).ready(function() {
  angular.bootstrap(document, ['lama']);
});

通过在karma导入的文件中包含您的手动引导程序,您的应用程序不一定在业力测试环境中被引导。因此,请将您的lama模块移动到单独的文件中,并从文件中省略init.js以包含在业力中。

还有一些其他设计问题导致过多的测试设置。在测试SystemController时,除了lama.system模块之外不需要包含任何内容(因为这是控制器所属的内容)。您对此控制器的测试设置可以简单如下:

var $scope, $rootScope;

beforeEach(module('system.lama'));

beforeEach(inject(function($controller, _$rootScope_) {
  $rootScope = _$rootScope_;
  $scope = $rootScope.$new();
  $controller('SystemController', {$scope: $scope});
}));

您将注意到,在如上所述隔离lama.system模块时,您将收到$state无法注入(未找到)的错误。这是因为您的模块定义应该是:

angular.module('lama.system', ['ui.router'])

(模块不应该为其自己的依赖项要求存在另一个模块,否则它永远不会孤立地运行。)

lama模块run块进行模拟的最后一个观察结果。严格来说,您应该完全保留服务query方法,而不仅仅是其实现的一部分,否则您的测试将完全隔离。因此,最好是执行以下操作:

beforeEach(module(function($provide) {
  $provide.decorator('Menus', function($delegate, $q) {
     // overwrite the query method
     $delegate.query = function() {
       return $q.when([{id: 1, name: 'Bob'}]);
     };    
     return $delegate; 
  });
}));

这样,您根本不必担心使用$httpBackend