ngMock将$ scope local注入控制器

时间:2016-01-05 21:19:48

标签: angularjs unit-testing scope angular-mock ngmock

这是成功回答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 = {}。为什么这样做会超过另一种?是否存在差异? ?

1 个答案:

答案 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函数。

<强>文档