我一直在学习如何测试我用角度来写的应用程序而且我感到困惑,因为它似乎有一些相互对立的东西。我试着跟随John Papa的style guide,以便我基本上使用Sidewaffle模板。目前看来,建议的模板和可测试性相互对立。
样式指南说有一个
控制器中的激活()
方法,它可以看到控制器的启动逻辑,如here所示。但是,一般测试指南说不应该测试私有方法。我有机会在提供的示例中测试activate()方法的结果,因为它将通过
传递vm.avengers
变量。在他的Pluralsight videos中,他使用common.activatecontroller()方法,他使用
$ q.all()
结合承诺,以便您可以在控制器激活阶段轻松调用许多功能。假设我有一个没有结果的函数可以通过vm传递,例如发布消息给WebApi来验证用户并获取令牌并将其设置为标题,或类似的东西。这是一个例子(服务没有注入,只是一个例子):
在下面的控制器中,唯一的业务逻辑是,当实例化控制器时,activate()方法调用调用OAuthenticationService.authenticate()方法的func1()方法。从测试的角度来看,服务是否被调用很重要。如何测试?
Here是一个非常相似的问题,其中一个答案表明我应该使用这样的关键字:
this.activate()
但是评论说它没有使用ControllerAs语法。我正在遵循ControllerAs语法。
当我在authenticate方法上使用spy为服务创建模拟时,测试表明我没有被调用,我认为由于该方法是私有的。
我没有想法......
提前感谢您的帮助!
示例
(function () {
'use strict';
angular
.module('app')
.controller('controller', controller);
controller.$inject = ['$location'];
function controller($location) {
/* jshint validthis:true */
var vm = this;
vm.title = 'controller';
activate();
function activate() {
func1();
}
function func1() {
OAuthAuthenticateService.authenticate(user).then(function() {
//setting up headers and other stuff, nothin will be part of $scope or vm;
});
}
}
})();
原始代码:
(function () {
'use strict';
var controllerId = 'requestAuthorizationController';
angular
.module('myapp')
.controller(controllerId, requestAuthorizationController);
requestAuthorizationController.$inject = ['$rootScope',
'$scope',
'requestAuthorizationService'
'Restangular'];
function requestAuthorizationController($rootScope,
$scope,
requestAuthorizationService
Restangular) {
/* jshint validthis:true */
var vm = this;
//other business logic
activate();
function activate() {
requestAuthorization();
}
function requestAuthorization() {
vm.fired = undefined;
requestAuthorizationService.getDummy();
}
}
})();
茉莉花测试:
'use strict';
describe('RequestAuthenticationController Specification', function () {
var RestangularProviderMock,
localStorageServiceProvider,
$httpProvider,
requestAuthorizationController,
requestAuthorizationServiceMock,
$rootScope;
//modules
beforeEach(function() {
angular.module('dilib.layout', []);
angular.module('http-auth-interceptor', []);
});
//providers
beforeEach(function () {
module('dilib', function(RestangularProvider, _localStorageServiceProvider_, _$httpProvider_, $provide) {
RestangularProviderMock = RestangularProvider;
localStorageServiceProvider = _localStorageServiceProvider_;
$httpProvider = _$httpProvider_;
$provide.service('requestAuthorizationService', function() {
this.getDummy = jasmine.createSpy('getDummy').and.callFake(function(num) {
});
});
});
});
//to crank up the providers
beforeEach(inject());
beforeEach(inject(function (_$rootScope_, _$controller_, _requestAuthorizationService_) {
$rootScope = _$rootScope_;
requestAuthorizationController = _$controller_;
requestAuthorizationServiceMock = _requestAuthorizationService_;
}));
describe('requestAuthorization function', function() {
it('RequestAuthorizationService.getDummy() is called', function() {
$rootScope.$digest();
expect(requestAuthorizationServiceMock.getDummy).toHaveBeenCalled();
});
});
});
答案 0 :(得分:0)
我认为我所采用的整个方法都是错误的。我在控制器中有太多的业务逻辑。根据{{3}}文章和其他文章,我必须尽可能地减少控制器中的业务逻辑,并将其置于服务公共方法中。如果我遵循这个规则,那么就不需要私有方法。但是,问题仍然与
有关激活()
方法。它足以测试执行函数的结果,即填充的视图模型?我想,答案是肯定的。
目前我专注于是否正确填充了视图模型变量,并且我将业务逻辑重构为服务。
在我看来,编写工作非常容易,但很难测试代码,而不是工作且易于测试代码。
故事的另一个方面是我作为测试员工作了10年,在测试的许多方面都有很好的经验。但是现在,我只是在摸索如何在可测试/测试驱动的开发方式上编写代码。 :)
答案 1 :(得分:0)
因此,在John Papa的风格指南中,activate()方法是一种抽象。如果您在构造函数方法中进行了大量设置,则将其抽象为activate()方法。然后你的构造函数是干净的。我不确定你发布的代码中有多少价值。
另外,您应该只对单元的API,外部接口进行单元测试。因此,对于控制器,视图中的操作调用的属性和方法。