【问题标题】:Unit testing controllers in angularJSangularJS 中的单元测试控制器
【发布时间】:2015-01-18 14:50:36
【问题描述】:

我很难理解 angularJs 中的单元测试。我刚刚开始进行单元测试,语法对我来说似乎很奇怪。下面是测试controller的代码:

describe('PhoneCat controllers', function() {

  describe('PhoneListCtrl', function(){

    beforeEach(module('phonecatApp'));

    it('should create "phones" model with 3 phones',
    inject(function($controller) {
      var scope = {},
      ctrl = $controller('PhoneListCtrl', {$scope:scope});

      expect(scope.phones.length).toBe(3);
    }));

  });
});

从这个语法我可以理解的是,在每个 it 块 phonecatApp 被初始化并且 $controller 服务用于获取 PhoneListCtrl 控制器的实例之前。 p>

但是我无法理解这里的范围。有人可以详细说明在这条线上获得控制器范围的背后是什么。

ctrl = $controller('PhoneListCtrl', {$scope:scope});

【问题讨论】:

    标签: angularjs unit-testing jasmine karma-runner karma-jasmine


    【解决方案1】:

    通常,在运行时,Angular 会创建一个作用域并将其注入到控制器函数中以对其进行实例化。 在您的单元测试中,您希望自己创建范围并将其传递给控制器​​功能,以便能够在构建后查看它是否确实有 3 个电话(例如)。

    您可能还想在控制器中注入模拟服务而不是真实服务。这就是对象数组所允许的

    $controller('PhoneListCtrl', {$scope:scope});
    

    它告诉 Angular:创建一个名为“PhoneListCtrl”的控制器实例,但不是创建和注入一个范围,而是使用我给你的那个。

    如果您的控制器依赖于服务“phoneService”,并且您想注入模拟 phoneService,您可以这样做

    var mockPhoneService = ...;
    $controller('PhoneListCtrl', { 
        $scope: scope,
        phoneService: mockPhoneService
    });
    

    【讨论】:

    • var scope={} 已定义,我们将 scope 作为参数传递给 PhoneListCtrl。所以它将成为那个控制器的局部变量。它是如何指向外部的 var scope ={} 的。我知道这里发生了其他事情,我的想法完全错误。请指导。
    • 您的控制器定义为app.controller('PhoneListCtrl', function($scope) { ... })。这个 $scope 参数是由 angular 注入的。在您的测试中,不是创建范围并注入它,而是 Angular 将您传递的那个作为参数并注入它。
    • 但是作用域对于该函数来说是本地的,它如何改变外部定义的 var scope ={}。
    • Angular 将对象的引用作为参数传递。所以测试有一个范围对象的引用,而 Angular 将这个范围对象的引用传递给控制器​​。因此,测试和控制器都有自己对同一个范围对象的引用。那是基本的 JavaScript 东西。在使用 Angular 之前,您应该了解 JavaScript 中的对象和变量。
    • 这是我不理解的内容。您能否在答案中添加此 javascript 概念的示例。谢谢。
    【解决方案2】:

    不需要注入作用域,你可以直接使用控制器的实例来调用控制器的函数和对象。在你的例子中你可以像下面这样使用,这将得到与你相同的结果集

    describe('PhoneCat controllers', function() {
    
      describe('PhoneListCtrl', function(){
    
         beforeEach(module('phonecatApp'));
    
           it('should create "phones" model with 3 phones',
               inject(function($controller) {
    
          var ctrl = $controller('PhoneListCtrl');
    
      expect(ctrl.phones.length).toBe(3);
      }));
    
      });
    });
    

    为您提供每次实例化控制器时的信息,它绑定到从 $rootScope 派生的 $scope 变量(即:rootscope 的子级)。所以你需要通过 $scope 来获取控制器的实例,我在上面的例子中做同样的事情。

    【讨论】:

    • 语法似乎更好,但它不起作用。请检查。
    • 当我使用 this.phones 而不在 PhoneListCtrl 中注入 $scope 时,您的版本可以工作。如果我错了,请纠正我。
    猜你喜欢
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 2014-02-06
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-28
    相关资源
    最近更新 更多