我们刚刚开始在AngularJS项目中实施茉莉花测试,我有一个问题:

我们要测试此控制器功能:

$scope.deleteClick = function () {
        $scope.processing = true;
        peopleNotesSrv.deleteNote($scope.currentOperator.operatorId, $scope.noteId, $scope.deleteSuccessCallback, $scope.deleteErrorCallback);
    };


我们编写了以下测试:

    it('deleteClick should pass proper parameters to peopleNoteSrv', function () {
        $controllerConstructor('PeopleNoteEditCtrl', { $scope: $scope });

        $scope.noteId = 5;

        expect(function () { $scope.deleteClick(); }).not.toThrow();
    });


此测试可确保在调用$ scope.deleteClick()函数时,将$ scope.processing设置为true,并且对PeopleNotesSrv的调用不会因参数无效而引发任何错误。我们正在单独的测试中测试这两个回调函数。

我们是否应该测试是否调用了peopleNotesSrv.deleteNote函数,以便使测试更加明确?现在编写此测试的方式并不能真正告诉别人deleteClick()函数的功能,这似乎是不正确的。

最佳答案

问问自己,如果使用TDD开发它会做什么。 Sam指出的方向差不多,但这是一些示例:

控制器测试


开始编写一个期望存在deleteClick的测试。
期望deleteClick以设置加载状态(检查处理情况是否为true)
测试是否将服务注入到控制器中(peopleNotesSrv)
检查deleteClick是否调用了该服务(如通过间谍所述)
验证是否存在并设置了$ scope.noteId和其他$ scope.params


这与控制器有关。它是否失败或引发错误等所有标准都应在Service.spec中进行测试。由于我在这里不了解您的详细服务,因此有一些示例

服务测试


确保deleteNote存在
检查如果提供了错误数量的参数(更少或更多)会发生什么情况
进行一些正面测试(例如您的noteId = 5)
做一些负面测试
确保正确调用回调


... 等等。

测试控制器中的有效性没有多大意义,因为您需要为那里的每个控制器都进行测试。通过将服务隔离为单独的测试单元并确保其满足所有要求,您无需测试即可直接使用它。这有点像您永远不会测试jQuery功能或使用Angular jQLite一样,因为您只是希望它们能够完成应做的事情:)

编辑:

使控制器测试在服务呼叫中失败

举个简单的例子。首先,我们创建服务测试以确保如果没有提供正确数量的参数,则调用将失败:

describe('Service: peopleNoteSrv', function () {

  // load the service's module
 beforeEach(module('angularControllerServicecallApp'));

 // instantiate service
 var peopleNoteSrv;
 beforeEach(inject(function (_peopleNoteSrv_) {
   peopleNoteSrv = _peopleNoteSrv_;
 }));

 it('should throw error on false number of arguments', function () {
   expect(function() { peopleNoteSrv.deleteNote('justOneParameter'); }).toThrow();
 });

});


现在,为了确保测试通过,让我们在服务方法中创建错误抛出部分

angular.module('angularControllerServicecallApp')
  .service('peopleNoteSrv', function peopleNoteSrv() {

    this.deleteNote = function(param1, param2, param3) {
      if(arguments.length !== 3)
        throw Error('Invalid number of arguments supplied');
      return "OK";
    };
});


现在让我们创建2个演示控制器,FirstCtrl会正确执行,但是SecondCtrl应该会失败

angular.module('angularControllerServicecallApp')
  .controller('FirstCtrl', function ($scope, peopleNoteSrv) {
    $scope.doIt = function() {
      return peopleNoteSrv.deleteNote('param1', 'param2', 'param3');
    }
  });

angular.module('angularControllerServicecallApp')
  .controller('SecondCtrl', function ($scope, peopleNoteSrv) {
    $scope.doIt = function() {
      return peopleNoteSrv.deleteNote('onlyOneParameter');
    }
  });


作为演示的两个控制器都经过以下测试:

it('should call Service properly', function () {
  expect(scope.doIt()).toBe("OK");
});


业力现在吐出这样的东西:

Error: Invalid number of arguments supplied
    at [PATH]/app/scripts/services/peoplenotesrv.js:15
    at [PATH]/app/scripts/controllers/second.js:13
    at [PATH]/test/spec/controllers/second.js:20


因此,您确切地知道您错过了更新SecondCtrl。当然,这对于使用Service方法的任何测试都应该有效。

希望这就是你的意思。

09-30 16:09
查看更多