茉莉是否可以访问角度指令控制器中定义的范围方法?

时间:2015-06-11 21:21:10

标签: angularjs jasmine angular-mock

我试图对下面的指令进行单元测试。我希望能够调用指令控制器($scope.save)中定义的函数,但我的测试似乎根本无法访问该范围。

我也试过isolateScope(),但是没有像我预期的那样返回内部$ scope对象。也许我做错了。

如何在下面的示例中获得myDir $ $范围? (如果你愿意,可以在这个小提琴上:http://jsfiddle.net/lalanl/8fkdsme3/



    angular.module('app', []).directive([
      function(myService) {

        return {
          restrict: 'E',
          templateUrl: 'path/to/template.html',
          scope: {
            info: "=info"
          },
          controller: function($scope) {
            $scope.someVal = 'porcupine';
            $scope.save = function() { /* ... */ };
          }
        }
      }
    ]);

    describe('myDir', function() {

      var $compile, $http, $httpBackend, $scope, $rootScope, $q;
      var element;

      beforeEach(module('app'));
      beforeEach(function() {
        inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
          $compile = _$compile_;
          $http = _$http_;
          $httpBackend = _$httpBackend_;
          $rootScope = _$rootScope_;
          $scope = $rootScope.$new();
          $q = _$q_;
        });

        $scope.data = "some data";
        element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
        $rootScope.$digest();
        $httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
      });

      it('should let me see its guts', function() {
        expect($scope.save).toBeTruthy();
        expect(typeof $scope.save).toBe("function");
      });

    });
&#13;
<html>

<head>
  <style type="text/css">
    @charset "UTF-8";
    [ng\:cloak],
    [ng-cloak],
    [data-ng-cloak],
    [x-ng-cloak],
    .ng-cloak,
    .x-ng-cloak,
    .ng-hide:not(.ng-hide-animate) {
      display: none !important;
    }
    ng\:form {
      display: block;
    }
  </style>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>SO question - jsFiddle demo</title>

  <script type="text/javascript" src="/js/lib/dummy.js"></script>




  <link rel="stylesheet" type="text/css" href="/css/result-light.css">


  <script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine.js"></script>



  <script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine-html.js"></script>



  <script type="text/javascript" src="http://jasmine.github.io/2.0/lib/boot.js"></script>



  <link rel="stylesheet" type="text/css" href="http://jasmine.github.io/2.0/lib/jasmine.css">



  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>



  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-mocks.js"></script>


  <style type="text/css">
  </style>



  <script type="text/javascript">
    //<![CDATA[ 

    angular.module('app', []).directive([
      function(myService) {

        return {
          restrict: 'E',
          templateUrl: 'path/to/template.html',
          scope: {
            info: "=info"
          },
          controller: function($scope) {
            $scope.someVal = 'porcupine';
            $scope.save = function() { /* ... */ };
          }
        }
      }
    ]);

    describe('myDir', function() {

      var $compile, $http, $httpBackend, $scope, $rootScope, $q;
      var element;

      beforeEach(module('app'));
      beforeEach(function() {
        inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
          $compile = _$compile_;
          $http = _$http_;
          $httpBackend = _$httpBackend_;
          $rootScope = _$rootScope_;
          $scope = $rootScope.$new();
          $q = _$q_;
        });

        $scope.data = "some data";
        element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
        $httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
      });

      it('should let me see its guts', function() {
        expect($scope.save).toBeTruthy();
        expect(typeof $scope.save).toBe("function");
      });

    });
     //]]>
  </script>


</head>

<body>

</body>

</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

这是一个更新的jsfiddle,您的测试使用内联指令模板。

编辑:管理以使其与外部模板一起使用。我忘了刷新我的http请求。我已更新完整答案,您可以看到更新的jsfiddle here

您的测试存在一些问题: -

  1. 在指令定义中,您没有给出指令名称。服务myService没有注入您的指令,但由于您没有正确定义您的指令,因此您没有收到该错误。
  2. 此外,您在使用之前删除的element.isolateScope()尝试获取元素的范围时是正确的。这是因为该指令将创建一个新的隔离范围。
  3. 您需要执行$ httpBackEnd.flush()来刷新外部模板的待处理请求。由于你没有这样做,你的测试中的$ compile没有看到模板而没有正确编译它。
  4. 我还做了一些其他的小改动,以使其发挥作用。

    P.S。如果您在项目中使用karma,我使用karma-ng-html2js-preprocessor来使用外部模板测试指令。看看here

    angular.module('app', []).directive('myDir', function () {
    
        return {
            restrict: 'E',
            //template: '<div>test:{{someVal}}</div>',
            templateUrl: 'path/to/template.html',
            scope: {
                info: "=info"
            },
            controller: function ($scope) {
                $scope.someVal = 'porcupine';
                $scope.save = function () { /* ... */
                };
            }
        }
    });
    
    describe('myDir', function () {
    
        var $compile, $scope, $rootScope;
        var element, isolatedScope;
    
        beforeEach(module('app'));
        beforeEach(inject(function (_$compile_, _$rootScope_, $httpBackend) {
            $httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
    
            $compile = _$compile_;
            $rootScope = _$rootScope_;
            $scope = $rootScope.$new();
    
            element = $compile('<my-dir info="data"></my-dir>')($scope);
            $httpBackend.flush();
            isolatedScope = element.isolateScope();
        }));
    
        it('should let me see its guts', function () {
            expect(isolatedScope.save).toBeTruthy();
            expect(typeof isolatedScope.save).toBe("function");
        });
    
    });