简体   繁体   English

Angular组件(带指令)测试

[英]Angular component (with a directive) testing

I have a component I want to test.我有一个要测试的组件。 The test fails with message测试失败并显示消息

AdminPanelComponent > should create AdminPanelComponent > 应该创建

TypeError: Cannot read property 'role' of undefined TypeError:无法读取未定义的属性“角色”

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: Z86408593C34AF77FDD90D错误属性: Object({ ngDebugContext: DebugContext_({ view: Object({ def: Object({ factory: Function, nodeFlags: 50577443, rootNodeFlags: 1, nodeMatchedQueries: 0, flags: 0, 节点: [ 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 :对象({}),ngContentIndex:null,childCount:11,绑定:[],bindingFlags:0,输出:[],元素:对象({ ns:'',名称:'div',attrs:[数组] , template: null, componentProvider: null, componentView: null, componentRendererType: null, publicProviders: null({ }), allProviders: null({ }), handleEvent: Z86408593C34AF77FDD90D F932F8B5261Z }), 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_web F932F8B5261Z }), 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 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 ) 在 checkAndUpdateNode ( http://localhost:9876/_karma_web pack_/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 ) pack_/node_modules/@angular/core/fesm2015/core.js:37072:1 ) 在 debugCheckAndUpdateNode ( http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38094:36 ) 在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 ) 在 callViewAction ( http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:374031: )

admin-panel.component.ts管理面板.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管理面板.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 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();
      }
    }
  }
}

The code part that is failing to work is无法工作的代码部分是

const userRoles = this.authService.decodedToken.role as Array<string>;

How do I test this component?如何测试这个组件?

The best way to test an angular app is to mock everything except the component you want to test.测试 angular 应用程序的最佳方法是模拟除您要测试的组件之外的所有内容。

The easiest way to do it is to use a lib like ng-mocks .最简单的方法是使用像ng-mocks这样的库。

Nevertheless you need to stub the AuthService like that不过,您需要像那样存根 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.
      },
    },
  ],
})

in this case AuthService will be a stub with fake methods that don't do anything.在这种情况下,AuthService 将是一个带有不做任何事情的假方法的存根。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM