使用Jasmine在Angular控制器中测试对象初始化

时间:2015-08-05 18:20:40

标签: javascript angularjs jasmine

我有一个控制器在控制器初始化时初始化一个对象,并且想测试它是否被实际调用它的特定参数调用。

我知道我可以测试$ scope.autoSaveObj有某些属性可以告诉我它实际上是初始化的,但是我如何监视初始化事件呢?

基本上,我想像我的方法一样监视新的autoSaveObj。

我想测试和监视对象构造函数的主要原因是我的karma-coverage插件会将这些行显示为覆盖。如果我只是在初始化后测试$ scope.autoSaveObject的状态,它就不会显示所覆盖的行。

App.controller('ItemCtrl',[ '$scope', function($scope){
  $scope.autoSaveObject = new autoSaveObj({
    obj: $scope.item,
    saveCallback: function() {
                  return $scope.saveItem();
                },
    errorCallback: null,
    saveValidation: $scope.validItem,
    delay: 2000
  });
}]);

1 个答案:

答案 0 :(得分:2)

我的猜测是代码示例是部分控制器,因为使用了$scope中未在此处初始化的属性。

由于autoSaveObj没有在任何地方定义,我认为它是一个全局函数。考虑将其移至服务或工厂。

以下示例显示了如何

  • mock autoSaveObj
  • 验证通话参数,
  • 验证创建的实例实际上是否为正确类型的实例。

angular.module('myApp', []).

controller('ItemCtrl', function($scope, $window) {
  // Use the injected $window object, so we don't rely on
  // the environment and it can be mocked easily.
  $scope.autoSaveObject = new $window.autoSaveObj({
    obj: $scope.item,
    saveCallback: function() {
      return $scope.saveItem();
    },
    errorCallback: null,
    saveValidation: $scope.validItem,
    delay: 2000
  });
});


describe('ItemCtrl', function() {
  var $controller;
  var $scope;
  var $window;
  var controller;

  beforeEach(module('myApp', function($provide) {
    $window = {
      // Create an actual function that can be spied on.
      // Using jasmine.createSpy won't allow to use it as a constructor.
      autoSaveObj: function autoSaveObj() {}
    };

    // Provide the mock $window.
    $provide.value('$window', $window);
  }));

  beforeEach(inject(function(_$controller_, $rootScope) {
    $controller = _$controller_;
    $scope = $rootScope.$new();
  }));

  it('should instantiate an autoSaveObj', function() {
    spyOn($window, 'autoSaveObj');
    // Initialize the controller in a function, so it is possible
    // to do preparations.
    initController();
    // Do function call expectations as you would normally.
    expect($window.autoSaveObj).toHaveBeenCalledWith(jasmine.objectContaining({
      saveCallback: jasmine.any(Function),
      delay: 2000
    }));
    // The autoSaveObject is an instance of autoSaveObj,
    // because spyOn was used, not jasmine.createSpy.
    expect($scope.autoSaveObject instanceof $window.autoSaveObj).toBe(true);
  });

  function initController() {
    controller = $controller('ItemCtrl', {
      $scope: $scope
    });
  }
});
<link href="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.css" rel="stylesheet"/>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-mocks.js"></script>