app.directive('xx',function () { return { bindToController: true,controller: 'xxCtrl',scope: { label: '@',},}; });
然后在控制器中我有一个默认情况下,在HTML中没有指定标签:
app.controller('xxCtrl',function () { var ctrl = this; ctrl.label = ctrl.label || 'default value'; });
如何在Jasmine单元测试中实例化xxCtrl,所以我可以测试ctrl.label?
describe('buttons.RemoveButtonCtrl',function () { var ctrl; beforeEach(inject(function ($controller) { // What do I do here to set ctrl.label BEFORE the controller runs? ctrl = $controller('xxCtrl'); })); it('should have a label',function () { expect(ctrl.label).toBe('foo'); }); });
检查this以测试该问题
挖掘AngularJS源代码我发现一个未记录的第三个参数的$ controller服务调用后(见$controller source)。
如果为true,$ controller()返回一个具有属性实例的函数,您可以在其上设置属性。
当准备好实例化控制器时,调用该函数,它将使用构造函数中提供的属性实例化控制器。
您的示例将工作如下:
describe('buttons.RemoveButtonCtrl',function () { var ctrlFn,ctrl,$scope; beforeEach(inject(function ($rootScope,$controller) { scope = $rootScope.$new(); ctrlFn = $controller('xxCtrl',{ $scope: scope,true); })); it('should have a label',function () { ctrlFn.instance.label = 'foo'; // set the value // create controller instance ctrl = ctrlFn(); // test expect(ctrl.label).toBe('foo'); }); });
这里有一个更新的Plunker(不得不升级Angular使其工作,现在是1.3.0-rc.4):http://plnkr.co/edit/tnLIyzZHKqPO6Tekd804?p=preview
注意,它可能不推荐使用它,引用Angular源代码:
Instantiate controller later: This machinery is used to create an
instance of the object before calling the controller’s constructor
itself.This allows properties to be added to the controller before the
constructor is invoked. Primarily,this is used for isolate scope
bindings in $compile.This feature is not intended for use by applications,and is thus not
documented publicly.
然而,缺乏一个机制来测试控制器与bindToController:真让我使用它,但也许。角球家伙应该考虑使该标志公开。
在引擎盖下,它使用一个临时构造函数,我们也可以自己写我猜猜。
您的解决方案的优势是构造函数不会被调用两次,如果属性没有像您的示例中的默认值,这可能会导致问题。
Angular 1.4(更新2015-12-06):
Angular团队在version 1.4.0增加了对此的直接支持。(参见#9425)
你可以只传递一个对象到$ controller函数:
describe('buttons.RemoveButtonCtrl',function () { var ctrl,$controller) { scope = $rootScope.$new(); ctrl = $controller('xxCtrl',{ label: 'foo' }); })); it('should have a label',function () { expect(ctrl.label).toBe('foo'); }); });
参见这blog post。