Javascript 如何正确测试AngularJS控制器功能
我们刚刚开始在AngularJS项目中实施jasmine测试,我有一个问题: 我们要测试此控制器功能:Javascript 如何正确测试AngularJS控制器功能,javascript,angularjs,jasmine,Javascript,Angularjs,Jasmine,我们刚刚开始在AngularJS项目中实施jasmine测试,我有一个问题: 我们要测试此控制器功能: $scope.deleteClick = function () { $scope.processing = true; peopleNotesSrv.deleteNote($scope.currentOperator.operatorId, $scope.noteId, $scope.deleteSuccessCallback, $scope.deleteEr
$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();
});
it('should call Service properly', function () {
expect(scope.doIt()).toBe("OK");
});
此测试确保在调用$scope.deleteClick()函数时,$scope.processing设置为true,并且对peopleNotesSrv的调用不会因为无效参数而引发任何错误。我们在单独的测试中测试这两个回调函数
我们是否应该测试调用了peopletesrv.deleteNote函数,以便测试更加明确?目前编写此测试的方式并没有真正告诉某人deleteClick()函数在引擎盖下的作用,这似乎是不正确的。我认为答案是这取决于它 有两种情况:
1-您还有一套针对PeopleNotesSV服务的测试 在本例中,我将保持此测试不变,或者检查$scope.deleteClick()的特定功能的更多内容,例如$scope.processing上是否有任何监视程序执行与.deleteClick()调用相关的任何特定操作
2-您没有对PeopleNotesSV服务的所有可能功能进行任何测试 在本例中,我将编写一个更显式的测试来检查.deleteNote()是否实际执行了它的任务
在我看来,你真的应该建立测试,尽量不要在多个地方测试同一件事情,因为这会增加额外的工作,并且可能会在测试中产生漏洞,如果你认为,“我可以在从调用它的特定函数调用这个特定情况时测试它。” 如果您想在不同的地方将deletNote()作为更大的函数的一部分重用,那么您需要为相同的代码编写另一个测试,因为它是从不同的函数调用的 因此,我将针对案例1,通过这种方式,您可以为该服务编写所有测试,然后相信这些测试涵盖了该特定测试的其余部分。如果您在错误的输入上抛出错误,或者在实际删除注释时失败,那么您应该信任其他代码来测试它设计用来测试的内容。这将大大加快您的测试编写时间,并增加您的测试覆盖所有案例的机会。它还将该服务的所有测试保持在测试代码中的同一位置 我想一个好问题是,这是什么样的测试?单元测试还是端到端测试 我假设这是一个针对我的答案的单元测试,如果这是一个端到端测试,那么您可能希望继续跟踪函数调用,以验证一切是否按照预期进行 这里有一些关于单元测试、端到端测试的链接,以及一篇关于和的非常好的文章
- (端到端测试也可以称为集成测试)
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('deleteClick should pass proper parameters to peopleNoteSrv', function () {
$controllerConstructor('PeopleNoteEditCtrl', { $scope: $scope });
$scope.noteId = 5;
expect(function () { $scope.deleteClick(); }).not.toThrow();
});
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。当然,这应该适用于使用服务方法的任何测试
希望这就是你的意思。是的,你可以模拟
peopletesrv
服务并监视deletNote方法……我们主要关心的是在服务上的签名更改时捕获错误。假设我们在服务调用中添加了一个新参数。我们希望现在调用该服务的所有控制器测试在没有正确参数的情况下都失败。你会怎么做呢?好的,我已经更新了我以前的答案,希望这就是你的意思