在我阅读有关Angularjs的所有教程和示例中,他们都定义了带有空列表的模块作为第二个参数:
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',
'ui.router',
'mean.system'
]);
我有什么理由不想做后者吗?为什么我从未在文档和教程中看到它 - 它会阻止我在测试中模拟这些依赖项吗?
为什么我不需要后一个子模块定义来定期运行我的应用程序?我确实有一系列注射当地人'为UserCtrl指定 - 为什么不足以进行单元测试?
答案 0 :(得分:3)
模块的目的是封装代码的自包含部分(例如,可重用的小部件,代码tgst实现特定的功能等)。通常,让每个模块声明它依赖的依赖项是一个好习惯。
如果没有,那么模块依赖于模块,它要求它声明那些依赖性,这会混淆“自我遏制”,损害可测试性和可重用性,并引入一堆如果潜在的未来错误。
也就是说,似乎没有理由不向每个模块声明依赖关系。 (不,它不会阻止你在单元测试中模拟依赖项。)正如人们所预料的那样,即使多个模块需要,每个模块也会加载一次。
API参考确实不是非常详细的angular.module
,但 Developer Guide 有更广泛的描述。
例如,引用“依赖关系”部分:
模块可以将其他模块列为其依赖项。根据模块的不同,需要在加载需求模块之前加载所需的模块。换句话说,所需模块的配置块在需求模块的配置块之前执行。运行块也是如此。 每个模块只能加载一次,即使有多个其他模块需要它。