在Karma(Angular 7)绊脚石的基础上建立单元测试的基础。
<testcase name="HeaderComponent should create" time="0.4" classname="HeaderComponent">
<failure type=""> Uncaught TypeError: Cannot read property 'eventType' of undefined thrown
此特定属性存在于queryObject
上,可在我的秋田状态管理器中使用,但是在HeaderComponent中不可用。也没有对秋田商店,queryObject或HeaderComponent中任何内容的引用。
这怎么可能是个问题?
组件:
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
menuHidden = true;
constructor(
private router: Router,
private i18nService: I18nService,
public authenticationService: AuthenticationService
) {}
ngOnInit() {}
toggleMenu() {
this.menuHidden = !this.menuHidden;
}
setLanguage(language: string) {
this.i18nService.language = language;
}
logout() {
this.authenticationService.logout().subscribe(() => this.router.navigate(['/login']));
}
get currentLanguage(): string {
return this.i18nService.language;
}
get languages(): string[] {
return this.i18nService.supportedLanguages;
}
get username(): string | null {
const credentials = this.authenticationService.credentials;
return credentials ? credentials.username : null;
}
}
规格:
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, NgbModule, TranslateModule.forRoot()],
declarations: [HeaderComponent],
providers: [{ provide: AuthenticationService, useClass: MockAuthenticationService }, I18nService]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
MockAuthenticationService
export class MockAuthenticationService {
credentials: Credentials | null = {
username: 'test',
token: '123'
};
login(context: LoginContext): Observable<Credentials> {
return of({
username: context.username,
token: '123456'
});
}
logout(): Observable<boolean> {
this.credentials = null;
return of(true);
}
isAuthenticated(): boolean {
return !!this.credentials;
}
isAuthenticatedAdmin(): boolean {
return true; // this.genericStateModel.isAdmin;
}
}
模板
<header>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="/" translate>APP_NAME</a>
<button class="navbar-toggler" type="button" aria-controls="navbar-menu"
aria-label="Toggle navigation" (click)="toggleMenu()" [attr.aria-expanded]="!menuHidden">
<span class="navbar-toggler-icon"></span>
</button>
<div id="navbar-menu" class="collapse navbar-collapse float-xs-none" [ngbCollapse]="menuHidden">
<div class="navbar-nav">
<a class="nav-item nav-link text-uppercase" routerLink="/herd" routerLinkActive="active">
<i class="fas fa-home"></i>
<span translate>herd</span>
</a>
<a *ngIf="authenticationService.isAuthenticated() && authenticationService.isAuthenticatedAdmin()" class="nav-item nav-link text-uppercase" routerLink="/stock" routerLinkActive="active">
<i class="fas fa-warehouse"></i>
<span translate>stock</span>
</a>
<a *ngIf="authenticationService.isAuthenticated() && authenticationService.isAuthenticatedAdmin()" class="nav-item nav-link text-uppercase" routerLink="/orders" routerLinkActive="active">
<i class="fas fa-money-check-alt"></i>
<span translate>orders</span>
</a>
</div>
<div class="navbar-nav ml-auto">
<div class="nav-item" ngbDropdown placement="bottom-right">
<a id="user-dropdown" class="nav-link" ngbDropdownToggle>
<i class="fas fa-user-circle"></i>
</a>
<div ngbDropdownMenu aria-labelledby="user-dropdown">
<h6 class="dropdown-header">
<span translate>logged in as</span> <b>{{username}}</b></h6>
<div class="dropdown-divider"></div>
<button class="dropdown-item" (click)="logout()" translate>logout</button>
</div>
</div>
</div>
</div>
</nav>
</header>