1

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

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

如何myDir在下面的示例中获得 's $scope?(或者如果你喜欢这个小提琴: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");
      });

    });
<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>

4

1 回答 1

2

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

编辑:设法让它与外部模板一起工作。我忘了刷新我的 http 请求。我已经更新了完整的答案,你可以在这里看到更新的 jsfiddle

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

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

为了使其正常工作,我还做了一些其他的小改动。

PS 如果您在项目中使用 karma,我使用 karma-ng-html2js-preprocessor 来测试使用外部模板的指令。看看这里

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");
    });

});
于 2015-06-11T22:36:49.233 回答