【问题标题】:Angular Unit Testing ControllersAngular 单元测试控制器
【发布时间】:2016-07-29 20:03:18
【问题描述】:

我的控制器除了在服务中调用方法之外没有做很多事情,服务包装并返回它的功能,我已经为模拟 http 请求的服务编写了单元测试。

在这种情况下是否值得对控制器进行单元测试?如果是,我将测试什么,因为我已经测试了服务功能。

下面是我的控制器:

'use strict';

/* Controllers */

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

 calculatorControllers.controller('BodyController', ['$scope',
function($scope) {
   $scope.toggleNavBarActive = function($event) {            
       $($event.currentTarget).parent().find('.active').removeClass('active');
      $($event.currentTarget).addClass('active');
   };
}]);

calculatorControllers.controller('CalculatorCtrl', ['$scope',    'CalculatorService',
function($scope, CalculatorService) {
$scope.orderProp = 'asc';
$scope.result = ' awaiting calculation';
$scope.sum = {};   

$scope.add = function(val1, val2) {         
    var promise = CalculatorService.add(val1, val2);  
    promise.then(function(response) {
        $scope.result = response;
    });     
};   
}]);

calculatorControllers.controller('AboutCtrl', ['$scope', '$routeParams',
  function($scope, $routeParams) {

}]);

【问题讨论】:

  • 请发布您的控制器的代码。否则,问题就太宽泛了。
  • 在我的应用程序中,我的大多数服务都向 API 发出请求并在将承诺返回给控制器之前处理响应。我的控制器通常在模板使用数据之前对响应做最少的工作。在某些情况下,我会在此之前修改数据,在这种情况下,可能需要对响应进行单元测试。这实际上取决于您的控制器 API 的简单程度和模块化程度。顺便说一句,你会柔术吗?只是因为你的用户名才问。
  • 嘿,是的,我会柔术,你呢?我现在是紫带。我希望我是 Angular 的紫色腰带,但我觉得自己像一条没有条纹的白色......
  • 根据@Pavlo 的要求,您能否包含有问题的控制器...
  • 目前只想测试一下计算器控制器,等我大致知道自己在做什么就担心机身控制器了。

标签: javascript angularjs unit-testing controllers


【解决方案1】:

控制器方法不需要测试的唯一情况是

$scope.calculator = CalculatorService;

所以像{{ calculator.sum(...) }} 这样的所有视图调用都是由服务完成的。

在所有其他情况下,都应测试控制器方法。由于CalculatorService 单元已经过测试,因此必须对其进行模拟,以便单独测试控制器逻辑。

【讨论】:

    【解决方案2】:

    是否值得在这种情况下对控制器进行单元测试

    是的,无论控制器还是服务,您都应该以 100% 的覆盖率为目标。我会在这里测试两件事(Jasmine):

    it('inits $scope', function() {
      var $scope = {};
      $controller('PasswordController', { $scope: $scope });
    
      expect($scope.orderProp).toEqual('asc');
      expect($scope.result).toEqual(' awaiting calculation');
      expect($scope.sum).toEqual({});
    });
    
    it('calls CalculatorService and sets the result', function() {
      var $scope = {};
      $controller('PasswordController', { $scope: $scope });
    
      $scope.sum(1, 2);
      expect(CalculatorServiceMock).toHaveBeenCalledWith(1, 2);
    
      resolveCalculatorServiceMockAddSpyWith(3);
      expect($scope.result).toEqual(3);
    });
    

    【讨论】: