angular.module('myModule',[]);
我知道创建一个新模块需要存在第二个参数,但我不明白为什么列表中没有任何元素. angular.module的文档没有说明列表内容的含义.
但是,通过定义我的app模块,我理解列表代表新模块所依赖的模块 – 那么为什么app子模块总是空的?例如,在我自己的项目中,我有一个用户模块,我的应用程序依赖于该模块:
/* app.js */ angular.module('myApp',[ 'ngCookies','ngResource','ui.bootstrap','ui.router','myApp.system','myApp.users' ]); angular.module('myApp.system',[]); angular.module('myApp.users',[]);
当我终于开始学习如何使用业力和茉莉花进行单元测试时,我花了好几个小时试图弄清楚这个错误信息:
Error: [$injector:modulerr] Failed to instantiate module myApp.users due to: Error: [$injector:unpr] Unknown provider: $stateProvider http://errors.angularjs.org/1.2.13/$injector/unpr?p0=%24stateProvider at /Users/matt/Development/myApp/public/lib/angular/angular.js:3556 at getService (/Users/matt/Development/myApp/public/lib/angular/angular.js:3683) at invoke (/Users/matt/Development/myApp/public/lib/angular/angular.js:3710) at /Users/matt/myApp/public/lib/angular/angular.js:3639
最终我找到了两个可以解决这个问题的东西 – 要么我可以在测试代码中加载模块依赖项,要么我可以将依赖项添加到users模块声明中的空列表中:
/* UserControllerTest.js */ describe('UserCtrl',function () { var $rootScope,$scope,controller; beforeEach(function () { module('ui.router'); module('myApp.system'); module('ngResource'); module('myApp.users'); inject(function ($injector) { $rootScope = $injector.get('$rootScope'); $scope = $rootScope.$new(); controller = $injector.get('$controller')('UserCtrl',{$scope: $scope}); }); }); it('should work',function () { expect(true).toBe(true); }); });
要么:
/* app.js */ ... angular.module('myApp.users',[ 'ngResource','mean.system' ]);
有什么理由我不想做后者吗?为什么我从未在文档和教程中看到它 – 它会阻止我在测试中模拟这些依赖项吗?
为什么我不需要后一个子模块定义来定期操作我的应用程序?我确实为UserCtrl指定了一系列’注入局部’ – 为什么单元测试不足够?
解决方法
如果没有,那么模块依赖于模块,因为它要求它声明那些依赖性,这会混淆“自我遏制”,损害可测试性和可重用性,并引入一堆如果潜在的未来错误.
也就是说,似乎没有理由不向每个模块声明依赖关系. (不,它不会阻止你在单元测试中模拟依赖关系.)正如人们所预料的那样,即使多个模块需要,每个模块也会加载一次.
关于angular.module的API参考确实不是很详细,但Developer Guide有更广泛的描述.
例如,引用“依赖关系”部分:
Modules can list other modules as their dependencies. Depending on a module implies that required module needs to be loaded before the requiring module is loaded. In other words the configuration blocks of the required modules execute before the configuration blocks of the requiring module. The same is true for the run blocks. Each module can only be loaded once,even if multiple other modules require it.