【问题标题】:Retrieving angular controller via $scope in unit test在单元测试中通过 $scope 检索角度控制器
【发布时间】:2015-09-13 09:22:27
【问题描述】:

我试图在我的 jasmine 测试中通过 $scope 检索控制器,但失败得很惨。有人知道为什么吗?

当使用controllerAs 语法时,控制器对象使用controllerAs 中指定的名称放在$scope 对象上。因此,通过使用 ng-app='MyApp' 在浏览器中运行下面的代码来引导到 angular,我可以使用 chrome-dev 工具来定位和选择指令元素,然后在控制台中键入 $0.scope().myDirCtrl。这确实产生了控制器对象,那么为什么我不能在我的单元测试中检索控制器对象呢?

运行下面的 sn-p 将启动一个独立的 jasmine 浏览器测试环境。测试规范列在 sn-p 的底部。我遇到问题的代码是这样的:

expect($scope.myDirCtrl).toBeDefined();

/* --------------------------------------
    Source code
   --------------------------------------*/
(function(angular) {
  'use strict';

  // Setup the template -----------------
  angular.module('MyApp.tpls', [])
  .run(['$templateCache', function($templateCache) {
    $templateCache.put('partials/myDirective.html',
                       '<div>{{myDirCtrl.testValue}}</div>');
  }]);

  // Setup the app ----------------------
  angular.module('MyApp', ['MyApp.tpls'])
    .directive('myDirective', myDirective)
    .controller('MyDirectiveController', MyDirectiveController);

  function myDirective() {
    return {
      restrict        : 'E',
      templateUrl     : 'partials/myDirective.html',
      transclude      : true,
      controllerAs    : 'myDirCtrl',
      bindToController: true,
      scope           : {},
      controller      : 'MyDirectiveController'
    };
  }

  MyDirectiveController.$inject = ['$scope'];
  function MyDirectiveController($scope) {
    var ctrl = this;
    ctrl.testValue = 'Only a test';
  }
})(angular);



/* --------------------------------------
    Test specifications
   --------------------------------------*/
(function (module) {
  'use strict';
  
  // Define the tests -------------------
  describe('My directive test', function () {
    var $compile, $rootScope, $scope;

    beforeEach(module('MyApp'));
    beforeEach(inject(function(_$compile_, _$rootScope_) {
      $compile   = _$compile_;
      $rootScope = _$rootScope_;
      $scope     = $rootScope.$new();
    }));

    it('scope should contain a controller reference', function () {
      var element = $compile(angular.element('<my-directive></my-directive>'))($scope);
      $scope.$digest();
      expect($scope.myDirCtrl).toBeDefined();
    });
  });
})(module);
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine.css">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine-html.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/boot.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular-mocks.js"></script>

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine


    【解决方案1】:

    问题是您的规范中的$scopeMyDirectiveController 中使用的范围不同。指令为控制器创建了一个范围,该范围成为您的规范范围的子级。您应该能够在测试中借助 Angular 内部属性来检查它:

    it('scope should contain a controller reference', function () {
        var element = $compile(angular.element('<my-directive></my-directive>'))($scope);
        $scope.$digest();
    
        // controller is actually in a child scope
        console.log($scope.$$childHead.myDirCtrl);
    
        expect($scope.myDirCtrl).toBeDefined();
    });
    

    但我不建议依赖这些私有 Angular 属性,例如 $$childHead,因为它们被认为是私有的,而不是公共 API 的一部分。我认为这个 Q/A AngularJS - Access to child scope 可以帮助您解决这个问题。

    【讨论】:

    • 你是对的。 expect(angular.element('&gt; *', element).scope().myDirCtrl).toBeDefined(); 为真。指令总是如此,还是仅对特定的 DDO 设置才如此?如果是后者,什么设置需要创建一个新的子范围来容纳控制器? transclue : true?
    • 在你的指令中你有一个属性scope: {}。通过定义这个额外的属性,您可以强制指令创建它自己的所谓“隔离”范围。 (docs)。如果您删除它,它将从父范围继承并且测试将通过。
    • 当然是facepalm。我实际上知道这一点,只是在我的单元测试中没有想到它......我真是太愚蠢了。非常感谢...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 2014-05-17
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多