Angular 组件(带指令)测试
Angular component (with a directive) testing
我有一个要测试的组件。测试失败并显示消息
AdminPanelComponent > should create
TypeError: Cannot read property 'role' of undefined
error properties: Object({ ngDebugContext: DebugContext_({ view:
Object({ def: Object({ factory: Function, nodeFlags: 50577443,
rootNodeFlags: 1, nodeMatchedQueries: 0, flags: 0, nodes: [ Object({
nodeIndex: 0, parent: null, renderParent: null, bindingIndex: 0,
outputIndex: 0, checkIndex: 0, flags: 1, childFlags: 50577443,
directChildFlags: 1, childMatchedQueries: 0, matchedQueries: Object({
}), matchedQueryIds: 0, references: Object({ }), ngContentIndex:
null, childCount: 11, bindings: [ ], bindingFlags: 0, outputs: [ ],
element: Object({ ns: '', name: 'div', attrs: [ Array ], template:
null, componentProvider: null, componentView: null,
componentRendererType: null, publicProviders: null({ }),
allProviders: null({ }), handleEvent: Function }), provider: null,
text: null, query: null, ngContent: null }), Object({ nodeIndex: 1,
parent: Object({ nodeIndex: 0, parent: null, renderParent: null,
bindingIndex: 0, outputIndex: 0, checkIndex: 0, flags: 1, childFlags:
50577443, directChildFlags: 1, chi ...
at
at HasRoleDirective.ngOnInit (http://localhost:9876/_karma_webpack_/src/app/_directives/hasRole.directive.ts:16:53)
at checkAndUpdateDirectiveInline (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:26276:1)
at checkAndUpdateNodeInline (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37133:1)
at checkAndUpdateNode (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37072:1)
at debugCheckAndUpdateNode (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38094:36)
at debugCheckDirectivesFn (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38037:1)
at Object.eval [as updateDirectives] (ng:///DynamicTestModule/AdminPanelComponent.ngfactory.js:62:5)
at Object.debugUpdateDirectives [as updateDirectives] (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38025:1)
at checkAndUpdateView (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37037:1)
at callViewAction (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37403:1)
admin-panel.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-admin-panel',
templateUrl: './admin-panel.component.html',
styleUrls: ['./admin-panel.component.css']
})
export class AdminPanelComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
admin-panel.component.html
<div class="container mt-5">
<h2>Admin panel</h2>
<div class="tab-panel">
<tabset class="member-tabset">
<tab heading="User Management" *appHasRole="['Admin']">
<div class="container">
<app-user-management></app-user-management>
</div>
</tab>
<tab heading="Photo management" *appHasRole="['Admin', 'Moderator']">
<app-photo-management></app-photo-management>
</tab>
</tabset>
</div>
</div>
hasRole.directive.ts
import { Directive, Input, ViewContainerRef, TemplateRef, OnInit } from '@angular/core';
import { AuthService } from '../_services/auth.service';
@Directive({
selector: '[appHasRole]'
})
export class HasRoleDirective implements OnInit {
@Input() appHasRole: string[];
isVisible = false;
constructor(private viewContainerRef: ViewContainerRef,
private templateRef: TemplateRef<any>,
private authService: AuthService) { }
ngOnInit() {
const userRoles = this.authService.decodedToken.role as Array<string>;
// if no roles clear the viewContainerRef
if (!userRoles) {
this.viewContainerRef.clear();
}
// if user has role need to render the element
if (this.authService.roleMatch(this.appHasRole)) {
if (!this.isVisible) {
this.isVisible = true;
this.viewContainerRef.createEmbeddedView(this.templateRef);
} else {
this.isVisible = false;
this.viewContainerRef.clear();
}
}
}
}
无法运行的代码部分是
const userRoles = this.authService.decodedToken.role as Array<string>;
如何测试这个组件?
测试 angular 应用程序的最佳方法是模拟除要测试的组件之外的所有内容。
最简单的方法是使用像 ng-mocks.
这样的库
尽管如此,您需要像这样对 AuthService 进行存根处理
TestBed.configureTestingModule({
declarations: [HasRoleDirective, AdminPanelComponent],
provides: [
{
provide: AuthService,
useValue: {
decodedToken: {
role: [], // <- you can put here values for the test
},
roleMatch: () => false, // <- or to use a spy here.
},
},
],
})
在这种情况下,AuthService 将是一个具有不执行任何操作的假方法的存根。
我有一个要测试的组件。测试失败并显示消息
AdminPanelComponent > should create
TypeError: Cannot read property 'role' of undefined
error properties: Object({ ngDebugContext: DebugContext_({ view: Object({ def: Object({ factory: Function, nodeFlags: 50577443, rootNodeFlags: 1, nodeMatchedQueries: 0, flags: 0, nodes: [ Object({ nodeIndex: 0, parent: null, renderParent: null, bindingIndex: 0, outputIndex: 0, checkIndex: 0, flags: 1, childFlags: 50577443, directChildFlags: 1, childMatchedQueries: 0, matchedQueries: Object({ }), matchedQueryIds: 0, references: Object({ }), ngContentIndex: null, childCount: 11, bindings: [ ], bindingFlags: 0, outputs: [ ], element: Object({ ns: '', name: 'div', attrs: [ Array ], template: null, componentProvider: null, componentView: null, componentRendererType: null, publicProviders: null({ }), allProviders: null({ }), handleEvent: Function }), provider: null, text: null, query: null, ngContent: null }), Object({ nodeIndex: 1, parent: Object({ nodeIndex: 0, parent: null, renderParent: null, bindingIndex: 0, outputIndex: 0, checkIndex: 0, flags: 1, childFlags: 50577443, directChildFlags: 1, chi ... at at HasRoleDirective.ngOnInit (http://localhost:9876/_karma_webpack_/src/app/_directives/hasRole.directive.ts:16:53) at checkAndUpdateDirectiveInline (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:26276:1) at checkAndUpdateNodeInline (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37133:1) at checkAndUpdateNode (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37072:1) at debugCheckAndUpdateNode (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38094:36) at debugCheckDirectivesFn (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38037:1) at Object.eval [as updateDirectives] (ng:///DynamicTestModule/AdminPanelComponent.ngfactory.js:62:5) at Object.debugUpdateDirectives [as updateDirectives] (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38025:1) at checkAndUpdateView (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37037:1) at callViewAction (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:37403:1)
admin-panel.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-admin-panel',
templateUrl: './admin-panel.component.html',
styleUrls: ['./admin-panel.component.css']
})
export class AdminPanelComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
admin-panel.component.html
<div class="container mt-5">
<h2>Admin panel</h2>
<div class="tab-panel">
<tabset class="member-tabset">
<tab heading="User Management" *appHasRole="['Admin']">
<div class="container">
<app-user-management></app-user-management>
</div>
</tab>
<tab heading="Photo management" *appHasRole="['Admin', 'Moderator']">
<app-photo-management></app-photo-management>
</tab>
</tabset>
</div>
</div>
hasRole.directive.ts
import { Directive, Input, ViewContainerRef, TemplateRef, OnInit } from '@angular/core';
import { AuthService } from '../_services/auth.service';
@Directive({
selector: '[appHasRole]'
})
export class HasRoleDirective implements OnInit {
@Input() appHasRole: string[];
isVisible = false;
constructor(private viewContainerRef: ViewContainerRef,
private templateRef: TemplateRef<any>,
private authService: AuthService) { }
ngOnInit() {
const userRoles = this.authService.decodedToken.role as Array<string>;
// if no roles clear the viewContainerRef
if (!userRoles) {
this.viewContainerRef.clear();
}
// if user has role need to render the element
if (this.authService.roleMatch(this.appHasRole)) {
if (!this.isVisible) {
this.isVisible = true;
this.viewContainerRef.createEmbeddedView(this.templateRef);
} else {
this.isVisible = false;
this.viewContainerRef.clear();
}
}
}
}
无法运行的代码部分是
const userRoles = this.authService.decodedToken.role as Array<string>;
如何测试这个组件?
测试 angular 应用程序的最佳方法是模拟除要测试的组件之外的所有内容。
最简单的方法是使用像 ng-mocks.
这样的库尽管如此,您需要像这样对 AuthService 进行存根处理
TestBed.configureTestingModule({
declarations: [HasRoleDirective, AdminPanelComponent],
provides: [
{
provide: AuthService,
useValue: {
decodedToken: {
role: [], // <- you can put here values for the test
},
roleMatch: () => false, // <- or to use a spy here.
},
},
],
})
在这种情况下,AuthService 将是一个具有不执行任何操作的假方法的存根。