这是成功回答another question I asked的延续。
我正在学习如何使用Karma,Jasmine和ngMock对AngularJS应用程序进行单元测试。这是我对以下问题的代码:
describe('myController function', function() {
describe('myController', function() {
var scope;
beforeEach(module('myApp'));
beforeEach(inject(function($rootScope, $controller) {
// These are the 2 lines I'm a bit confused about:
scope = $rootScope.$new();
$controller('MyController', {$scope: scope});
}));
it("...");
});
});
问题1:为什么我们要创建一个新的scope
并将其包含在此行的本地注入区域中:$controller('MyController', {$scope: scope});
?它似乎工作得很好(因为,scope
现在表示来自该控制器的$scope
对象并具有它应该具有的所有属性和功能,但代码似乎意味着我们正在重置控制器的$scope
包含我们新创建的(和空的)scope
(来自行scope = $rootScope.$new();
)。所以我想我还没有完全理解那些当地人的目的/内部运作。
问题2:我也从我的搜索中看到,新的scope
以两种常见方式创建,可以采用上面$rootScope.$new()
显示的方式,也可以通过简单声明scope = {}
。即使是Angular文档也是这两种方式,如here(使用$rootScope.$new()
)和here(使用$scope = {}
。为什么这样做会超过另一种?是否存在差异? ?
答案 0 :(得分:2)
为什么要创建新范围
有几个原因可以想到,但简短的回答是,如果你不想,你就不会 。您可以轻松地传入$rootScope
,您的测试仍然有效。它也只是通常完成,因为它更符合角度实际发生的情况 - 控制器注入的$scope
可能是$rootScope
的后代。
什么是$ controller(' MyController',{$ scope:scope});做吗
ngMock
模块提供$controller
函数作为一种用于创建控制器的构造函数 - 从技术上讲,它是$controller
函数的ng
装饰器。模块,但这并不重要。第一个参数通常是一个字符串,但可以是一个函数。
如果使用函数调用,那么它被认为是控制器构造函数。否则,它被认为是一个字符串,用于检索控制器构造函数......
第二个参数是"本地人"在创建期间注入控制器。
所以,在你的例子中,你是说你要创建" MyController"您希望在控制器函数中将scope
变量作为名为$scope
的参数注入。
整个的目的是将您自己的scope
版本注入控制器,但是您在测试中创建的版本,以便您可以断言不同的东西由于控制器而发生在范围内。
这是依赖注入的好处之一。
<强>实施例强>
如果以下内容有意义:
var scope = {};
scope.add = function(){};
expect(typeof scope.add).toBe('function');
然后让我们更进一步,将函数添加到另一个函数中:
var addFunctionToScope = function(scope) {
scope.add = function(){};
};
var scope = {};
addFunctionToScope(scope);
expect(typeof scope.add).toBe('function');
现在只是假装你的新函数将函数添加到范围实际上只是调用$ controller,而不是&#34; addFunctionToScope&#34;。
var scope = {};
$controller('SomeController', {$scope: scope});
expect(typeof scope.add).toBe('function');
为什么要使用$ rootScope。$ new()而不是{}
同样,您可以使用其中之一。但是,如果您计划使用某些范围特定的函数,例如$on
,$new
或$watch
等,则需要注入一个实际的范围对象,使用现有范围的$ new函数。
<强>文档强>