簡體   English   中英

AngularJS單元測試:初始化指令控制器的范圍

[英]AngularJS unit tests: Initialize scope of a directive's controller

對於使用“ controller as”語法的單獨控制器的指令,我具有以下代碼:

'use strict';

angular.module('directives.featuredTable', [])

.controller('FeaturedTableCtrl',
['$scope',
function ($scope){
  var controller = this;

  controller.activePage = 1;
  controller.changePaginationCallback =
    controller.changePaginationCallback || function(){};
  controller.density = 10;
  controller.itemsArray = controller.itemsArray || [];
  controller.metadataArray = controller.metadataArray || [];
  controller.numberOfItems = controller.numberOfItems || 0;
  controller.numberOfPages = 1;
  controller.options = controller.options || {
    'pagination': false
  };

  controller.changePaginationDensity = function(){
    controller.activePage = 1;
    controller.numberOfPages =
      computeNumberOfPages(controller.numberOfItems, controller.density);

    controller.changePaginationCallback({
      'page': controller.activePage,
      'perPage': controller.density
    });
  };

  controller.getProperty = function(object, propertyName) {
    var parts = propertyName.split('.');

    for (var i = 0 ; i < parts.length; i++){
      object = object[parts[i]];
    }

    return object;
  };

  controller.setActivePage = function(newActivePage){
    if(newActivePage !== controller.activePage &&
      newActivePage >= 1 && newActivePage <= controller.numberOfPages){

      controller.activePage = newActivePage;
      controller.changePaginationCallback({
        'page': controller.activePage,
        'perPage': controller.density
      });
    }
  };

  initialize();

  $scope.$watch(function () {
    return controller.numberOfItems;
  }, function () {
    controller.numberOfPages =
      computeNumberOfPages(controller.numberOfItems, controller.density);
  });

  function computeNumberOfPages(numberOfItems, density){
    var ceilPage = Math.ceil(numberOfItems / density);
    return ceilPage !== 0 ? ceilPage : 1;
  }

  function initialize(){
    if(controller.options.pagination){
      console.log('paginate');
      controller.changePaginationCallback({
        'page': controller.activePage,
        'perPage': controller.density
      });
    }
  }
}]
)

.directive('featuredTable', [function() {
return {
  'restrict': 'E',
  'scope': {
    'metadataArray': '=',
    'itemsArray': '=',
    'options': '=',
    'numberOfItems': '=',
    'changePaginationCallback': '&'
  },
  'controller': 'FeaturedTableCtrl',
  'bindToController': true,
  'controllerAs': 'featuredTable',
  'templateUrl': 'directives/featuredTable/featuredTable.tpl.html'
};
}]);

您可以在控制器的開頭看到我正在使用指令傳遞的屬性或提供默認值來初始化其屬性:

controller.activePage = 1;
controller.changePaginationCallback =
    controller.changePaginationCallback || function(){};
controller.density = 10;
controller.itemsArray = controller.itemsArray || [];
controller.metadataArray = controller.metadataArray || [];
controller.numberOfItems = controller.numberOfItems || 0;
controller.numberOfPages = 1;
controller.options = controller.options || {
  'pagination': false
};

最后,我要執行initialize(); 將根據選項執行回調的函數:

function initialize(){
  if(controller.options.pagination){
    controller.changePaginationCallback({
      'page': controller.activePage,
      'perPage': controller.density
    });
  }
}

我現在正在嘗試對該控制器(使用業力和茉莉花)進行單元測試,並且需要“模擬”該指令傳遞的參數,我嘗試了以下操作:

'use strict';

describe('Controller: featured table', function () {

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

  var scope;
  var featuredTable;
  var createCtrlFn;
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();

    createCtrlFn = function(){
      featuredTable = $controller('FeaturedTableCtrl', {
        '$scope': scope
      });
      scope.$digest();
    };
  }));

  it('should initialize controller', function () {
    createCtrlFn();

    expect(featuredTable.activePage).toEqual(1);
    expect(featuredTable.changePaginationCallback)
      .toEqual(jasmine.any(Function));
    expect(featuredTable.density).toEqual(10);
    expect(featuredTable.itemsArray).toEqual([]);
    expect(featuredTable.metadataArray).toEqual([]);
    expect(featuredTable.numberOfPages).toEqual(1);
    expect(featuredTable.numberOfItems).toEqual(0);
    expect(featuredTable.options).toEqual({
      'pagination': false
    });
  });

  it('should initialize controller with pagination', function () {
    scope.changePaginationCallback = function(){};
    spyOn(scope, 'changePaginationCallback').and.callThrough();

    scope.options = {
      'pagination': true
    };

    createCtrlFn();

    expect(featuredTable.activePage).toEqual(1);
    expect(featuredTable.changePaginationCallback)
      .toEqual(jasmine.any(Function));
    expect(featuredTable.density).toEqual(10);
    expect(featuredTable.itemsArray).toEqual([]);
    expect(featuredTable.metadataArray).toEqual([]);
    expect(featuredTable.numberOfPages).toEqual(1);
    expect(featuredTable.numberOfItems).toEqual(0);
    expect(featuredTable.options).toEqual({
      'pagination': true
    });

    expect(featuredTable.changePaginationCallback).toHaveBeenCalledWith({
      'page': 1,
      'perPage': 10
   });
  });
});

並得到以下錯誤,這意味着范圍未正確初始化:
期望的Object({分頁:false})等於Object({分頁:true})
在test / spec / app / rightPanel / readView / historyTab / historyTab.controller.spec.js:56

模擬綁定將是不平凡的-畢竟,這是很難真正知道什么是編譯和鏈接指令與傳遞給它...除非你只是做了自己的數據呢!

該angular.js文件提供了關於如何編譯和鏈接進行單元測試指令指南- https://docs.angularjs.org/guide/unit-testing#testing-directives 之后,您只需要從結果元素中獲取控制器(請參閱此處的controller()方法的文檔-https: //docs.angularjs.org/api/ng/function/angular.element )和執行您的測試。 ControllerAs在這里無關緊要-您將直接測試控制器,而不是操縱范圍。

這是一個示例模塊:

var app = angular.module('plunker', []);

app.controller('FooCtrl', function($scope) {
  var ctrl = this;

  ctrl.concatFoo = function () {
    return ctrl.foo + ' world'
  }
})
app.directive('foo', function () {
  return {
    scope: {
      foo: '@'
    },
    controller: 'FooCtrl',
    controllerAs: 'blah',
    bindToController: true,
  }
})

並測試設置:

describe('Testing a Hello World controller', function() {
  ctrl = null;

  //you need to indicate your module in a test
  beforeEach(module('plunker'));

  beforeEach(inject(function($rootScope, $compile) {
    var $scope = $rootScope.$new();
    var template = '<div foo="hello"></div>'
    var element = $compile(template)($scope)

    ctrl = element.controller('foo')

  }));

  it('should produce hello world', function() {
    expect(ctrl.concatFoo()).toEqual('hello world')
  });
});

(實時演示: http : //plnkr.co/edit/xoGv9q2vkmilHKAKCwFJ?p=preview

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM