为了更加像Angular 2.0,我决定以传统的方式消除对控制器的定义:
e.g。
return {
restrict: 'E',
controller: 'MyCtrl',
controllerAs: 'vm',
bindToController: true,
scope: {},
templateUrl: 'path/to/tempate.html'
}
在这里我们可以看到控制器名称作为字符串传递,这意味着我们在某处定义了类似的内容:
app.controller('MyCtrl', function(...));
在传统测试中,我只是将$controller
服务注入测试中以检索MyCtrl
控制器。但是我决定这样做:
return {
restrict: 'E',
controller: MyCtrl,
controllerAs: 'vm',
bindToController: true,
scope: {},
templateUrl: 'path/to/tempate.html'
}
这里唯一的区别是传递给控制器声明的是一个名为MyCtrl的函数。这似乎一切都很好,但是你会去检索这个控制器并进行测试吗?
我试过这样做:
var $compile, $rootScope, $httpBackend, element, ctrl;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$rootScope_, _$httpBackend_) {
$compile = _$compile_;
$rootScope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
element = $compile('<directive></directive>')($rootScope);
ctrl = element[0].controller;
});
});
但是在上面我得到 undefined 回来给控制器。有没有其他人让这一举动更像Angular 2.0?在测试方面有什么不同?
由于
P.S语法更改的想法是,在我们这样做时,可以轻松升级到Angular 2.0。
修改
我花了最后一两天试图检索控制器,唯一有效的方法似乎只是以传统方式传递控制器。这是我尝试过的方法列表(请参阅评论以确定每个输出的内容)
(function() {
'use strict';
/*
This part is used just for testing the html rendered
*/
describe('flRequestPasswordReset template: ', function() {
var $compile, $rootScope, $templateCache, template, element, ctrl;
var path = 'templates/auth/fl-request-password-reset/fl-request-password-reset.html';
beforeEach(module('app'));
beforeEach(module(path));
beforeEach(inject(function(_$compile_, _$rootScope_, _$templateCache_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$templateCache = _$templateCache_;
// Using nghtml2js to retrieve our templates
template = $templateCache.get(path);
element = angular.element(template);
$compile(element)($rootScope.$new());
$rootScope.$digest();
// $rootScope has a reference to vm which is what my
// controllerAs defines but only contains one of the variables
// This returns undefined
ctrl = element.controller('flRequestPasswordReset');
}));
it('should be defined', function() {
expect(element).toBeDefined();
});
});
describe('flRequestPasswordReset: template with controller: ', function() {
var $compile, $rootScope, $httpBackEnd, element, ctrl;
var path = '/templates/auth/fl-request-password-reset/fl-request-password-reset.html';
beforeEach(module('app'));
beforeEach(inject(function(_$compile_, _$rootScope_, _$templateCache_, _$httpBackend_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$httpBackEnd = _$httpBackend_;
$httpBackEnd.expectGET(path).respond({});
element = angular.element('<fl-request-password-reset></fl-request-password-reset>');
$compile(element)($rootScope.$new());
$rootScope.$digest();
// Uses alternate name for directive but still doesn't get the
// controller
ctrl = element.controller('fl-request-password-reset');
}));
it('should be defined', function() {
expect(element).toBeDefined();
});
});
/*
This part is used for testing the functionality of the controller by itself
*/
xdescribe('flRequestPasswordReset: just controller', function() {
var scope, ctrl;
beforeEach(module('app'));
beforeEach(inject(function($controller, $rootScope) {
scope = $rootScope;
// Instantiate the controller without the directive
ctrl = $controller('FlRequestPasswordResetController', {$scope: scope, $element: null});
}));
it('should be defined', function() {
expect(true).toBe(true);
});
/*
This works because I moved the controller back to the old way
*/
});
}());
根据我对pkozlowski.opensource下的this问题的理解,您可以使用将控制器作为函数传递,只要您不将其封装在指令中。这种方式在全球范围内暴露出来。这是一件坏事,因为它污染了全局命名空间,但他似乎建议在构建应用程序时将其包装起来。
我对此的理解是否正确?