角单元测试:“ mat-nav-list”不是已知元素

时间:2019-05-15 08:55:36

标签: angular typescript unit-testing dependencies angular5

我目前正在使用旧的Angular 5代码,除了使用Angular CLI生成组件时的默认测试外,没有任何单元测试。

该项目使用的是Angular Material 5 RC0,看来单元测试没有考虑到我模块的依赖关系。

app.module.ts:

@NgModule({
  declarations: [
    AppComponent,
    /* My module components... */
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    ReactiveFormsModule,
    BrowserAnimationsModule,
    routing,
    DialogsModule,
    SharedModule ,
    MaterialModule,
    MatListModule, // It's the module that should be needed
    MatSidenavModule,
    ToastrModule.forRoot({
      timeOut: 5000,
      positionClass: 'toast-bottom-right',
      preventDuplicates: true
    }),
    HttpClientModule,
    TableFactoryModule
  ],
  providers: [
    /* My module services */,
    AuthGuard
  ],
  bootstrap: [AppComponent]

})
export class AppModule {

}

app.component.ts:

import { Component, Input, ViewChild } from '@angular/core';
import { Router, RouterModule, ActivatedRoute } from '@angular/router';
import { HttpErrorResponse } from '@angular/common/http';
import { JwtHelperService } from '@auth0/angular-jwt';
import * as _ from 'lodash';

import { Subscription } from 'rxjs/Subscription';
import { ToastrService } from 'ngx-toastr';

import { UsersService } from 'app/services/users.service';
import { ComplexesService } from 'app/services/complexes.service';
import { ActivatedUserService } from 'app/shared/activateduser.service';
import { ActivatedComplexesService } from 'app/shared/activatedcomplexes.service';

import { User } from 'app/user';
import { Complex } from './complex/complex'
import { MatSidenav } from '@angular/material';
import { MatList } from '@angular/material/list'


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';
  isConnected = false;
  private subscription;
  private currentUser: User;
  userSubscription: Subscription;
  complexesSubscription: Subscription;
  @ViewChild(MatSidenav) sidenav: MatSidenav;

  constructor(
    private usersService: UsersService,
    private complexesService: ComplexesService,
    private router: Router,
    private toastr: ToastrService,
    private activatedUser: ActivatedUserService,
    private activatedComplexes: ActivatedComplexesService,
  ){
  }
  ngOnInit() {
    let getToken = this.usersService.isConnected();
    if (getToken) {
      this.getComplexes();
      this.userGetById();      
    }
    else
      this.router.navigate(['']);

    this.userSubscription = this.activatedUser.activatedUser$
    .subscribe(user => {
      if(user) {
        this.currentUser = user;
        this.sidenav.open();
      }
    });
  }
  logout(){
    this.usersService.logout();
    this.isConnected = this.usersService.isConnected();
    this.router.navigate(['']);
  }
  ngOnDestroy() {
    this.userSubscription.unsubscribe();
    this.complexesSubscription.unsubscribe();    
  }

  private userGetById(){
    let token = JSON.parse(localStorage.getItem('futbakCurrentUser'));
    let jwtHelperService: JwtHelperService = new JwtHelperService({});
    let currentUser = jwtHelperService.decodeToken(token);
    this.usersService.getByID(currentUser.id).subscribe(
      (res) => {
        this.currentUser = res
      }, (err: HttpErrorResponse) => {
        if (err.error instanceof Error) {
          // A client-side or network error occurred. Handle it accordingly.
          this.toastr.error("Une erreur est survenue : "+err.error.message  , '', { closeButton: true });
        } else {
          this.toastr.error("Une erreur est survenue code : "+ err.status+", message : "+err.statusText, '', { closeButton: true });
        }
      },
      () => {
        if(this.currentUser.role == 'superadmin' || this.currentUser.role == 'complexmanager') {
          this.activatedUser._activatedUser$.next(this.currentUser)
        }
        if(this.currentUser.role == 'superadmin') {
          this.router.navigate(['usersList']);
          this.getComplexes();
        } else if (this.currentUser.role == 'complexmanager') {
          this.router.navigate(['admins/'+this.currentUser._id])
        } else {
          this.toastr.error("Vous n'avez pas les droits pour accèder à l'application.",'',{closeButton :true});
        }
      });
  }

  private getComplexes(){
   return this.complexesService.get()
    .subscribe(
      res => {
        if(res)
          this.activatedComplexes._activatedComplexes$.next(res)
    }, (err: HttpErrorResponse) => {
        if (err.error instanceof Error) {
          this.toastr.error("Une erreur est survenue : "+err.error.message  , '', { closeButton: true });
        } else {
          this.toastr.error("Une erreur est survenue code : "+ err.status+", message : "+err.statusText, '', { closeButton: true });       
        }
      },
      () => {
      });
  }

 }

测试失败:

it('should create the app', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));

app.component.html:

<mat-sidenav-container fullscreen >

  <mat-sidenav #sidenav mode="side" disableClose>
    <!-- sidenav content -->

    <div><img src="./assets/logo.png" class="logo" ></div>
    <div class="title-app">
      <h2>Admin</h2>
    </div>

    <mat-nav-list>
      <a mat-list-item routerLinkActive="active" routerLink="['usersList']">
        <!-- <mat-icon fontSet="fa" fontIcon="fa-users" ></mat-icon> -->
        <i class="fa fa-users fa-fw fa-lg"></i> Joueurs
      </a>
      <a mat-list-item routerLink="['adminsList']">
        <i class="fa fa-user fa-fw fa-lg"></i> Admins
      </a>
      <a mat-list-item routerLinkActive="active" routerLink="['gamesList']">
          <i class="fa fa-futbol-o fa-fw fa-lg"></i> Matchs
      </a>
      <a mat-list-item routerLinkActive="active"  routerLink="['playgroundsList']">
        <i class="fa fa-cubes fa-fw fa-lg"></i> Terrains
      </a>
      <a mat-list-item routerLinkActive="active" routerLink="['complexesList']">
        <i class="fa fa-cube fa-fw fa-lg"></i> Complexes
      </a>
      <a mat-list-item routerLinkActive="active" routerLink="['devicesList']">
        <i class="fa fa fa-share-alt fa-fw fa-lg"></i> Capteurs
      </a>
      <a mat-list-item routerLinkActive="active" routerLink="['experimental', 'playgrounds']">
        <i class="fa fa fa-share-alt fa-fw fa-lg"></i> Business
      </a>
      <a mat-list-item routerLinkActive="active" routerLink="['experimental', 'devices']">
        <i class="fa fa fa-share-alt fa-fw fa-lg"></i> Technique
      </a>
    </mat-nav-list>
    <mat-nav-list class="account">
        <button mat-button (click)="logout()"><i class="fa fa-sign-out"></i> Déconnexion</button>
    </mat-nav-list>

  </mat-sidenav>
  <div class="main mat-typography">
    <!-- primary content -->
    <router-outlet ></router-outlet>
  </div>
</mat-sidenav-container>

最后,错误:

Failed: Template parse errors:
'mat-nav-list' is not a known element:
1. If 'mat-nav-list' is an Angular component, then verify that it is part of this module.
2. If 'mat-nav-list' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("
    </div>

    [ERROR ->]<mat-nav-list>
      <a mat-list-item routerLinkActive="active" routerLink="['usersList']">
       "): ng:///DynamicTestModule/AppComponent.html@10:4

因此,如您所见,我已经尝试过这种解决方案:

以此类推。

我在单元测试中只有这个问题,网站运行正常。

1 个答案:

答案 0 :(得分:2)

测试要求您手动导入模块。例如,它允许您在需要时加载“样机服务”,而不是实际的。

您将在同一文档页面上找到相应的文档here和相关主题。

因此,您将必须在测试文件中(describe项目内部)重新导入所需的模块,例如:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [ /* Your component */ ],
    imports: [
      /* Here, import your Angular material modules */
    ],
    providers: [
      /* Here, use custom or usual providers for your injected services */
    ]
  })
  .compileComponents();
}));