Unit testing 使用<;选择>;

Unit testing 使用<;选择>;,unit-testing,angularjs,angularjs-directive,jasmine,Unit Testing,Angularjs,Angularjs Directive,Jasmine,我有一个名为的指令,用于呈现html: angular.module('myApp.directives'). directive('dimension', ['$rootScope', 'Dimension', function($rootScope, Dimension) { return { restrict: 'E', scope: { ngModel: '=', inputs: '=inputsModel',

我有一个名为
的指令,用于呈现html:

angular.module('myApp.directives').
  directive('dimension', ['$rootScope', 'Dimension', function($rootScope, Dimension) {
    return {
      restrict: 'E',
      scope: {
        ngModel: '=',
        inputs: '=inputsModel',
        url: '@',
        listenFor: '@',
        broadcastOnChange: '@'
      },
      controller: function($scope, $element, $attrs, $transclude, Dimension) {
        this.get = function() {
          Dimension.get($attrs.url, $scope.inputs).then(function(data) {
            $scope.alloptions = data;
          });
        };
      },
      link: function($scope, $element, $attrs, $controller) {
        $controller.get();

        // Listen for changes to select, and broadcast those changes out to rootScope
        var dimension = $($element).find('select');
        dimension.on('change', function(event) {
          $rootScope.$broadcast('DimensionDirective.change', $attrs.broadcastOnChange);
        });

        // Listen for the broadcast, and react if the value of the broadcast is in the listen-for attribute list
        $rootScope.$on('DimensionDirective.change', function(event, value) {
          if (value == $scope.listenForArray) {
            $controller.get();
          }
        });
      },
      template:
          '<div>' + 
            '<label ng-transclude></label>' +
            '<fieldset>' +
                '<div class="form-group">' +
                  '<select ng-model="ngModel" ng-options="x for x in alloptions" multiple class="form-control"></select>' +
                '</div>' +
             '</fieldset>' +
          '</div>',
      replace: true,
      transclude: true
    };
  }]).
  factory('Dimension',
    ["$http", function($http) {
      return {
        get: function(_url, _inputs) {
          var future;
          future = $http({
            url: _url,
            method: 'POST',
            data: _inputs
          });
          return future.then(function(response) {
            return response.data;
          });
        }
      };
    }
  ]);
angular.module('myApp.directives')。
指令('dimension',['$rootScope','dimension',函数($rootScope,dimension){
返回{
限制:'E',
范围:{
ngModel:“=”,
输入:'=inputsModel',
网址:“@”,
列表名称:“@”,
broadcastOnChange:“@”
},
控制器:函数($scope、$element、$attrs、$transclude、Dimension){
this.get=函数(){
Dimension.get($attrs.url,$scope.inputs)。然后(函数(数据){
$scope.alloptions=数据;
});
};
},
链接:函数($scope、$element、$attrs、$controller){
$controller.get();
//侦听要选择的更改,并将这些更改广播到rootScope
变量维度=$($元素).find('select');
维度.on('change',函数(事件){
$rootScope.$broadcast('DimensionDirective.change',$attrs.broadcastOnChange);
});
//侦听广播,如果广播的值在侦听属性列表中,则作出反应
$rootScope.$on('DimensionDirective.change',函数(事件,值){
if(值==$scope.listenForArray){
$controller.get();
}
});
},
模板:
'' + 
'' +
'' +
'' +
'' +
'' +
'' +
'',
替换:正确,
转移:对
};
}]).
工厂('尺寸',
[“$http”,函数($http){
返回{
get:函数(_url,_inputs){
var期货;
future=$http({
url:_url,
方法:“POST”,
数据:_输入
});
返回future.then(函数(响应){
返回响应数据;
});
}
};
}
]);
现在,我想创建一个单元测试,以验证从xhr加载元素后,select中的元素数量是否正确。我创建了一个大致如下的单元测试:

describe('directive', function() {
  var $httpBackend;

  beforeEach(module('myApp.directives'));

  beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
    $httpBackend = _$httpBackend_;
    $httpBackend.expectPOST('url').
      respond(["Item 1", "Item 2"]);
  }));

  it('should load select\'s options from xhr on render', function() {
    inject(function($compile, $rootScope) {
      var element = $compile('<dimension ng-model="inputs.model" url="url">Dimension</dimension>')($rootScope);
      var select = element.find('select');
      expect(element.find('select').length).toBe(2); //TODO this isn't right.
    });
  });
});
描述('directive',function()){
var$httpBackend;
在每个模块之前(模块('myApp.directions');
beforeach(注入(函数($httpBackend_$rootScope,$controller){
$httpBackend=\$httpBackend\;
$httpBackend.expectPOST('url')。
答复([“第1项”、“第2项]);
}));
它('应该在渲染时从xhr加载select'选项',函数(){
注入(函数($compile,$rootScope){
var元素=$compile('Dimension')($rootScope);
var select=element.find('select');
expect(element.find('select').length).toBe(2);//TODO这不对。
});
});
});
然而,最后一个expect()并没有做正确的事情。
关于如何测试
是否加载了正确的信息并显示它,您有什么建议吗?

我发现您的测试代码有三个问题:

  • 您没有调用
    $httpBackend.flush
    ,因此没有模拟HTTP响应
  • 您没有触发摘要循环,因此Angular没有呈现指令的标记
  • 您试图计算有多少
    select
    被渲染,但始终只有一个。您应该计算生成了多少个
    选项
所有这些问题都很容易解决(为了弄清楚发生了什么,我对您的代码做了一点修改):

描述('directive',function()){
var$httpBackend;
beforeach(函数(){
模块(“myApp.directives”);
注入(函数($httpBackend_$rootScope$controller){
$httpBackend=\$httpBackend\;
});
});
它('应该在渲染时从xhr加载select'选项',函数(){
注入(函数($compile,$rootScope){
//安排
$httpBackend.expectPOST('url')。响应([“项目1”,“项目2]”);
var元素=$compile('Dimension')($rootScope);
//表演
$httpBackend.flush();//模拟响应
$rootScope.$digest();//触发摘要循环
//断言
expect(element.find('option').length).toBe(2);
});
});
});

下面是一个脚本,上面的测试正在运行。

我发现您的测试代码有三个问题:

  • 您没有调用
    $httpBackend.flush
    ,因此没有模拟HTTP响应
  • 您没有触发摘要循环,因此Angular没有呈现指令的标记
  • 您试图计算有多少
    select
    被渲染,但始终只有一个。您应该计算生成了多少个
    选项
所有这些问题都很容易解决(为了弄清楚发生了什么,我对您的代码做了一点修改):

描述('directive',function()){
var$httpBackend;
beforeach(函数(){
模块(“myApp.directives”);
注入(函数($httpBackend_$rootScope$controller){
$httpBackend=\$httpBackend\;
});
});
它('应该在渲染时从xhr加载select'选项',函数(){
注入(函数($compile,$rootScope){
//安排
$httpBackend.expectPOST('url')。响应([“项目1”,“项目2]”);
var元素=$compile('Dimension')($rootScope);
//表演
$httpBackend.flush();//模拟响应
$rootScope.$digest();//触发摘要循环
//断言
expect(element.find('option').length).toBe(2);
});
});
});

下面是一个脚本,上面的测试正在运行。

维度是包含该模板的指令吗?可以粘贴指令的代码吗?是的,维度是包含模板的指令。可以发布指令的代码吗?发布指令代码。
维度
是包含该模板的指令吗?你能粘贴指令的代码吗?是的,dimension是包含模板的指令。你能发布指令的代码吗
describe('directive', function() {
  var $httpBackend;

  beforeEach(function() {
    module('myApp.directives');

    inject(function(_$httpBackend_, $rootScope, $controller) {
      $httpBackend = _$httpBackend_;
    });
  });

  it('should load select\'s options from xhr on render', function() {
    inject(function($compile, $rootScope) {
      // Arrange
      $httpBackend.expectPOST('url').respond(["Item 1", "Item 2"]);
      var element = $compile('<dimension ng-model="inputs.model" url="url">Dimension</dimension>')($rootScope);

      // Act
      $httpBackend.flush(); // Simulates a response
      $rootScope.$digest(); // Triggers a digest cycle

      // Assert
      expect(element.find('option').length).toBe(2); 
    });
  });
});