仅具有专用功能的AngularJS单元测试控制器

仅具有专用功能的AngularJS单元测试控制器,angularjs,unit-testing,Angularjs,Unit Testing,我有以下控制器,只有私人功能。我正在努力测试这个控制器。既然ImageService已经过测试,我是否应该测试它是否正在执行$emit?在这种情况下,如何测试$emit?或者我应该测试它是否正在调用ImageService.fetchImageStacks方法?在这种情况下,如何触发init函数 (function (angular, global, undefined) { 'use strict'; var ImageController = {}; ImageController.$i

我有以下控制器,只有私人功能。我正在努力测试这个控制器。既然ImageService已经过测试,我是否应该测试它是否正在执行$emit?在这种情况下,如何测试$emit?或者我应该测试它是否正在调用ImageService.fetchImageStacks方法?在这种情况下,如何触发init函数

(function (angular, global, undefined) {
'use strict';

var ImageController = {};

ImageController.$inject = [
    '$rootScope',
    '$log',
    'ImageService'
];

ImageController = function (
    $rootScope,
    $log,
    ImageService
) {

    var getImageStacks = function() {
        ImageService
            .fetchImageStacks()
            .success(function (result) {
                ImageService.setImageStacks(result);
                $rootScope.$emit('rootScope:imageStacksUpdated', result);
            })
            .error(function (){
                $log.error('Failed to get imageStackInfo file.');
            });
    };

    var init = function () {
        getImageStacks();
    };

    init();

    return {
        getImageStacks: getImageStacks
    };
}

angular.module('myApp')
    .controller('ImageController', ImageController);

})(angular, this);

您不应该测试外部世界(imho)不可用的私有/内部方法

关于该主题的一些资源(赞成和反对):


也就是说,您正在控制器上公开
getImageStacks
,因此它不是私有方法。如果要注销在测试套件中实例化控制器的结果,您应该会看到以下内容:

{getImageStacks:function}

init()

无论如何,写一些测试

首先,您应该
stub
退出
ImageService
,因为我们对所述服务的内部实现不感兴趣,我们只对从控制器到服务的通信感兴趣。一个伟大的存根/嘲弄/间谍库是——得到它,你不会后悔的

在每个
之前的
中,我建议您这样做:

// Stub out the ImageService
var ImageService = {
  fetchImageStacks: sinon.stub(),
  setImageStacks: sinon.stub()
};

var $scope, instantiateController;

beforeEach(function () {
  // Override the ImageService residing in 'your_module_name'
  module('your_module_name', function ($provide) {
    $provide.value('ImageService', ImageService);
  });

  // Setup a method for instantiating your controller on a per-spec basis.
  instantiateController = inject(function ($rootScope, $controller, $injector) {
    ctrl = $controller('ImageController', {
      $scope: $rootScope.$new(),
      // Inject the stubbed out ImageService.
      ImageService: $injector.get('ImageService')
    });
  });
});
现在,您有了一个用于测试调用的存根ImageService,以及一个使用传递到它的依赖项实例化控制器的方法

您可以运行的一些示例规范

it('calls the ImageService.fetchImageStacks method on init', function () {
  instantiateController();
  expect(ImageService.fetchImageStacks).to.have.been.calledOnce;
});

it('calls the ImageService.setImageStacks on success', inject(function ($q, $timeout) {
  ImageService.getImageStacks.returns($q.when('value'));
  instantiateController();
  $timeout.flush();
  expect(ImageService.setImageStacks).to.have.been.calledOnce.and.calledWith('value');
}));
我希望这就足够了,并回答你关于的问题

  • 如果/何时应该/不应该测试内部实现
  • 如何测试控制器的初始化
  • 如何测试注入服务的方法

我很高兴能帮上忙!