ngMock 将 $scope local 注入控制器
ngMock injecting $scope local into controller
这是已成功回答的 的延续。
我正在学习如何使用 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
并将其包含在locals注入区的这一行:$controller('MyController', {$scope: scope});
?它似乎工作得很好(例如,scope
现在表示来自该控制器的 $scope
对象并具有它应该具有的所有属性和功能),但代码似乎暗示我们正在重置控制器的 $scope
与我们新创建的(和空的)scope
(来自 scope = $rootScope.$new();
行)。所以我想我只是没有完全理解那些当地人的 purpose/inner-workings。
问题 2: 我也从搜索中看到,新的 scope
是通过两种常见方式创建的,要么是上面显示的 $rootScope.$new()
,或者简单地声明 scope = {}
。即使是 Angular 文档也是两种方式,如 here (using $rootScope.$new()
) and here 所示(使用 $scope = {}
。为什么要这样做而不是另一种方式?有区别吗?
为什么我们要创建一个新的作用域
有几个原因浮现在脑海中,但简短的回答是,如果您不想,就没有。您可以轻松地传入 $rootScope
并且您的测试仍然有效。它通常也是这样做的,因为它更符合 angular 中实际发生的情况 - 注入控制器的 $scope
可能是 $rootScope
.[=30= 的后代]
什么是$controller('MyController', {$scope: scope});在做什么?
ngMock
模块提供 $controller
函数作为创建控制器的一种构造函数 - 好吧,从技术上讲,它是 [=19= 中 $controller
函数的装饰器] 模块,但这并不重要。第一个参数通常是一个字符串,但也可以是一个函数。
If called with a function then it's considered to be the controller constructor function. Otherwise it's considered to be a string which is used to retrieve the controller constructor...
第二个参数是 "locals" 在创建期间注入到控制器中。
所以,在你的例子中,你说你想创建 "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,而不是 "addFunctionToScope"。
var scope = {};
$controller('SomeController', {$scope: scope});
expect(typeof scope.add).toBe('function');
为什么要使用 $rootScope.$new() 而不是 {}
同样,您可以使用其中任何一个。但是,如果您计划使用某些作用域特定函数,例如 $on
、$new
或 $watch
等——您将需要注入一个实际的作用域对象,该对象使用现有作用域上的 $new 函数。
文档
这是已成功回答的
我正在学习如何使用 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
并将其包含在locals注入区的这一行:$controller('MyController', {$scope: scope});
?它似乎工作得很好(例如,scope
现在表示来自该控制器的 $scope
对象并具有它应该具有的所有属性和功能),但代码似乎暗示我们正在重置控制器的 $scope
与我们新创建的(和空的)scope
(来自 scope = $rootScope.$new();
行)。所以我想我只是没有完全理解那些当地人的 purpose/inner-workings。
问题 2: 我也从搜索中看到,新的 scope
是通过两种常见方式创建的,要么是上面显示的 $rootScope.$new()
,或者简单地声明 scope = {}
。即使是 Angular 文档也是两种方式,如 here (using $rootScope.$new()
) and here 所示(使用 $scope = {}
。为什么要这样做而不是另一种方式?有区别吗?
为什么我们要创建一个新的作用域
有几个原因浮现在脑海中,但简短的回答是,如果您不想,就没有。您可以轻松地传入 $rootScope
并且您的测试仍然有效。它通常也是这样做的,因为它更符合 angular 中实际发生的情况 - 注入控制器的 $scope
可能是 $rootScope
.[=30= 的后代]
什么是$controller('MyController', {$scope: scope});在做什么?
ngMock
模块提供 $controller
函数作为创建控制器的一种构造函数 - 好吧,从技术上讲,它是 [=19= 中 $controller
函数的装饰器] 模块,但这并不重要。第一个参数通常是一个字符串,但也可以是一个函数。
If called with a function then it's considered to be the controller constructor function. Otherwise it's considered to be a string which is used to retrieve the controller constructor...
第二个参数是 "locals" 在创建期间注入到控制器中。
所以,在你的例子中,你说你想创建 "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,而不是 "addFunctionToScope"。
var scope = {};
$controller('SomeController', {$scope: scope});
expect(typeof scope.add).toBe('function');
为什么要使用 $rootScope.$new() 而不是 {}
同样,您可以使用其中任何一个。但是,如果您计划使用某些作用域特定函数,例如 $on
、$new
或 $watch
等——您将需要注入一个实际的作用域对象,该对象使用现有作用域上的 $new 函数。
文档