Angular 1.5 单元测试控制器,需要父组件的控制器
Posted
技术标签:
【中文标题】Angular 1.5 单元测试控制器,需要父组件的控制器【英文标题】:Angular 1.5 unit test controller that requires parent component's controller 【发布时间】:2016-10-31 21:19:25 【问题描述】:我正在尝试对需要父组件和来自另一个模块的控制器的 AngularJS 1.5(带有 Webpack)组件的(子)控制器进行单元测试。
子控制器结构:
function ChildController ()
var vm = this;
vm.searchText = '';
vm.submit = function()
var data = ;
data['srch'] = vm.searchText;
vm.parentCtrl.submitTextSearch(data);
;
module.exports = ChildController;
子组件:
var template = require('./child.html');
var controller = require('./child.controller');
var childComponent =
require:
parentCtrl: '^parent'
,
template: template,
controller: controller,
controllerAs: 'vm'
;
module.exports = childComponent;
所以我想做的是模拟出 childController 的 submit() 函数中所需的 parentCtrl。我一直无法找到如何真正做到这一点。我找到了一些类似的子父指令解决方案并尝试了这些,例如通过this child-parent directive example 中描述的假HTML 元素注入父控制器,基本相同*** solutions 没有结果。我的问题至少不同之处在于子控制器和父控制器位于不同的模块中。而且我认为范围技巧不是 Angular 1.5 风格的?
没有失败的模拟尝试的 Jasmine 测试框架:
describe('child component', function()
describe('child controller', function()
var controller;
beforeEach(angular.mock.module('child'));
beforeEach(inject(function(_$componentController_)
controller = _$componentController_('child');
))
it('should work', function()
controller.searchText = "test";
controller.submit();
)
)
)
这导致TypeError: Cannot read property 'submitTextSearch' of undefined
。我应该怎么做才能模拟父控制器?由于我在 Angular 方面的经验有限,我没有想法。
【问题讨论】:
【参考方案1】:使用下面的代码将初始化它,请检查 Jasmine 单元测试Plunker
var ctrP = $componentController('parentComp');
var ctrl = $componentController('childComp', ,
parentCtrl: ctrP
);
你的测试用例应该如下图所示:
'use strict';
describe('component: heroDetail', function()
var $componentController, $compile, $rootScope;
beforeEach(module('plunker'));
beforeEach(inject(function(_$componentController_)
$componentController = _$componentController_;
));
it('should expose a `hero` object', function()
var ctrP = $componentController('parentComp');
console.log(ctrP);
var ctrl = $componentController('childComp', ,
parentCtrl: ctrP
);
console.log(ctrl);
ctrl.submit('some data');
expect(ctrl.parentCtrl.searchText).toEqual('some data');
);
);
【讨论】:
【参考方案2】:1.解决方案
在您的测试中,使用新范围实例化父控制器:
mainScope = $rootScope.$new();
$controller('ParentController', $scope: mainScope);
然后在您的子控制器中,使用之前实例化的作用域实例化一个新作用域:
childScope = mainScope.$new();
$controller('ChildController', $scope: childScope);
来自AngularJS documentation的示例:
describe('state', function()
var mainScope, childScope, grandChildScope;
beforeEach(module('myApp'));
beforeEach(inject(function($rootScope, $controller)
mainScope = $rootScope.$new();
$controller('MainController', $scope: mainScope);
childScope = mainScope.$new();
$controller('ChildController', $scope: childScope);
grandChildScope = childScope.$new();
$controller('GrandChildController', $scope: grandChildScope);
));
it('should work', function()
grandChildScope.searchText = "test";
grandChildScope.submit();
);
);
2.解决方案
子控制器结构:
function ChildController ()
var vm = this;
vm.searchText = '';
vm.submit = function()
var data = ;
data['srch'] = vm.searchText;
vm.parentCtrl.submitTextSearch(data);
;
module.exports = ChildController;
子组件:
var template = require('./child.html');
var controller = require('./child.controller');
var childComponent =
bindings:
searchText: 'test'
,
template: template,
controller: controller,
controllerAs: 'vm'
;
module.exports = childComponent;
var ChildController = $componentController('childComponent', null, ...);
ChildController.$onInit();
expect(ChildController.searchText).to.equal('test');
expect(ChildController.submit()).to.equal('*expected result value should come here*');
参考:
AngularJS documentation - Testing Controllers
AngularJS documentation - $componentController
Unit Testing Angular Components with $componentController
【讨论】:
【参考方案3】:在您的情况下,您将添加 parentCtrl
作为组件的依赖项,因此为了测试它,您还必须模拟父组件并将其分配给控制器。因此,您需要执行以下操作:
beforeEach(inject(function(_$componentController_)
controller = _$componentController_('child');
parentCtrl = _$componentController_('parent');
controller.parentCtrl = parentCtrl;
))
【讨论】:
我已经尝试过了,但对我不起作用。仍然得到“无法找到指令'以上是关于Angular 1.5 单元测试控制器,需要父组件的控制器的主要内容,如果未能解决你的问题,请参考以下文章
Angular 1.5 组件通过 ngRoute 更新父控制器