我正在尝试为Angular 1.5中的组件编写单元测试。我想对该组件及其dom节点进行单元测试。该组件包含一个非常复杂的子组件。
我的目标是在不编译子组件的情况下对外部组件进行单元测试。
由于我也想测试DOM,因此使用$ componentController进行此测试是不够的。
以下是我想要实现的一个简短示例:
组件代码:
angular.module('app').component('myComponent', {
bindings: {
username: '<',
},
template: `
<span>{{ $ctrl.username }}</span>
<my-complex-component />
`
controller: function () {}
});
my-component的单元测试:
it('my-component should render username', function () {
var template = '<my-component username="username"></my-component>',
element,
scope,
date;
scope = $rootScope.$new();
scope.username = 'John';
element = $compile(template)(scope);
scope.$digest();
username = element.find('span');
expect(username.text()).to.be.equal('John');
});
我的复杂组件不应该被实例化。它应该在模板中抵制。在单元测试中创建元素应该导致
<span>John</span>
<my-complex-component />
有没有办法做到这一点?
答案 0 :(得分:4)
Here is a very good explanation如何测试组件而不在当前组件下渲染整个树。
你想要的是什么叫
浅渲染(避免渲染子组件的整个模板)
并且Angular 1.5不提供开箱即用的功能。
如果您查看上面的链接,Wojciech Zawistowski将展示如何使用下面的帮助程序来实现浅层渲染。
export function componentSpyOn(name) {
function componentSpy($provide) {
componentSpy.bindings = [];
$provide.decorator(name + 'Directive', ($delegate) => {
let component = $delegate[0];
component.template = '';
component.controller = class {
constructor() {
componentSpy.bindings.push(this);
}
};
return $delegate;
});
}
return componentSpy;
}
答案 1 :(得分:2)
您可以使用$compileProvider.directive
覆盖您的子组件,即使它是一个组件,因为组件是一种特殊的指令。
在您的单元测试中,使用与您的子组件同名的编译器注册一个新组件,但不提供控制器并将模板设置为空字符串。这将导致组件没有任何逻辑/复杂性:
beforeEach(module('app', function($compileProvider){
$compileProvider.directive('myComplexComponent', function (){
return {
priority: 9999,
terminal: true,
template: ''
};
});
}));
因此,生成的html将是您的外部组件单元测试的最佳选择:
<span>John</span>
答案 2 :(得分:0)
有一种方法可以测试它,但最终结果将是:
<span>John</span>
<ng-transclude></ng-transclude>
组件代码:
angular.module('app').component('myComponent', {
enter code herebindings: {
username: '<',
},
template: `
<span>{{ $ctrl.username }}</span>
<ng-transclude></ng-transclude>
`,
transclude: true, // Added property
controller: function () {}
});
如您所见,我删除了<my-complex-component>
,并添加了<ng-transclude>
。
这意味着您可以从外部添加信息,并将其注入ng-transclude的位置。
例如,在你的主html中:
<my-component>
<my-complex-component></my-complex-component>
</my-component>
将以您想要的方式从DOM开始:
<span>John</span>
<my-complex-component></my-complex-component>
之后你的测试应该有效。
我希望这个答案是你想要的,它会帮助你。
答案 3 :(得分:0)
您可以使用空模块覆盖单元测试中的子组件模块定义。
// Unit Test Parent component
describe('Unit Testing: myComponent Component', () => {
beforeEach(() => {
// overwrite module
angular.module('myComplexComponent', []);
module('myComponent');
});
});
现在,父组件仍会尝试注入和呈现子组件,但由于此子组件完全为空,因此不会发生任何事情。