我有几个组件(关于、服务、仪表板等),其中添加了标头组件。该应用程序运行良好。但是,我在测试时遇到错误。
import { Component } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { SettingsPage } from './settings.page';
describe('SettingsPage', () => {
let component: SettingsPage;
let fixture: ComponentFixture<SettingsPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ SettingsPage,MockHeaderComponent ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(SettingsPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@Component({
selector: 'app-header',
template: ''
})
class MockHeaderComponent {
}
第一个错误
Chrome 93.0.4577.82 (Windows 10): Executed 22 of 26 (1 FAILED) (0 secs / 5.88 secs)
ERROR: 'NG0303: Can't bind to 'headline' since it isn't a known property of 'app-header'.'
headline 是我在标头组件中声明的变量,并在我的组件中使用它来为我提供正确的标题。
当然,我已经在互联网上寻找解决方案,并发现了以下 Stack Overflow 帖子: 使用 Jasmine 和 Karma 对 Angular 进行单元测试,错误:无法绑定到“xxx”,因为它不是“的已知属性” xxxxxx'. 因此,我导入并声明了我的 HeaderComponent。
import { Component } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { HeaderComponent } from '../header/header.component';
import { SettingsPage } from './settings.page';
describe('SettingsPage', () => {
let component: SettingsPage;
let fixture: ComponentFixture<SettingsPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ SettingsPage,HeaderComponent,MockHeaderComponent ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(SettingsPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@Component({
selector: 'app-header',
template: ''
})
class MockHeaderComponent {
}
不幸的是,出现了以下错误。
Chrome 93.0.4577.82 (Windows 10) SettingsPage should create FAILED
Failed: NG0300: Multiple components match node with tagname app-header. Find more at https://angular.io/errors/NG0300
error properties: Object({ code: '300' })
Error: NG0300: Multiple components match node with tagname app-header. Find more at https://angular.io/errors/NG0300
at throwMultipleComponentError (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:6779:1)
at findDirectiveDefMatches (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10344:1)
at resolveDirectives (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10158:1)
at elementStartFirstCreatePass (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:14772:1)
at ɵɵelementStart (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:14809:1)
at ɵɵelement (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:14888:1)
at SettingsPage_Template (ng:///SettingsPage.js:8:9)
at executeTemplate (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9600:1)
at renderView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9404:1)
at renderComponent (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10684:1)
Error: Expected undefined to be truthy.
at <Jasmine>
at UserContext.<anonymous> (src/app/components/settings/settings.page.spec.ts:24:23)
at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:364:1)
at ProxyZoneSpec.push.QpwO.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:292:1)
Chrome 93.0.4577.82 (Windows 10): Executed 26 of 26 (7 FAILED) (1.712 secs / 1.658 secs)
谁能告诉我我做错了什么?
更新1: 我的 ComponentsModule 类,其中集成了所有可重用组件:
import {NgModule} from '@angular/core';
import {HeaderComponent} from './header/header.component';
import { FooterComponent } from './footer/footer.component';
@NgModule({
declarations: [HeaderComponent, FooterComponent],
exports: [HeaderComponent, FooterComponent]
})
export class ComponentsModule{}
我的html:
<ion-header>
<app-header [headline]="headlines.settings"></app-header>
</ion-header>
<ion-content>
</ion-content>
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { SettingsPageRoutingModule } from './settings-routing.module';
import { SettingsPage } from './settings.page';
import { ComponentsModule } from '../components.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
ComponentsModule,
SettingsPageRoutingModule
],
declarations: [SettingsPage]
})
export class SettingsPageModule {}
设置.page.ts
import { Component, OnInit } from '@angular/core';
import { lablesHeadlines } from 'src/environments/lables';
@Component({
selector: 'app-settings',
templateUrl: './settings.page.html',
styleUrls: ['./settings.page.scss'],
})
export class SettingsPage implements OnInit {
lablesHeadlines = lablesHeadlines;
headlines = lablesHeadlines;
constructor() { }
ngOnInit() {
}
}
设置.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { SettingsPageRoutingModule } from './settings-routing.module';
import { SettingsPage } from './settings.page';
import { ComponentsModule } from '../components.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
ComponentsModule,
SettingsPageRoutingModule
],
declarations: [SettingsPage]
})
export class SettingsPageModule {}
问题已解决。https://testing-angular.com/testing-components-with-children/#testing-components-with-children向我展示了解决方案。我编写单元测试,我可以用 schemas: [NO_ERRORS_SCHEMA] 忽略顶级组件中的组件。低级组件已准备好在自己的测试中进行检查。 如果您想了解 Angular 测试,我强烈建议您使用上面的链接。
这是我更新的源代码:
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { AboutClientServiceService } from 'src/app/services/about-client-service.service';
import { AppComponent } from 'src/app/app.component';
import { MockAboutClientService } from 'src/app/Mock/MockAboutClientService';
import { AboutPage } from './about.page';
import { Component } from '@angular/core';
import { NO_ERRORS_SCHEMA } from '@angular/core';
describe('AboutPage', () => {
let component: AboutPage;
let fixture: ComponentFixture<AboutPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AboutPage, MockHeaderComponent ],
schemas: [NO_ERRORS_SCHEMA],
imports: [IonicModule, HttpClientTestingModule],
providers: [AppComponent, AboutClientServiceService]
}).compileComponents();
TestBed.overrideComponent(
AboutPage,
{
set: {
providers: [
{ provide: AboutClientServiceService, useClass: MockAboutClientService }]
}
});
fixture = TestBed.createComponent(AboutPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', (done) => {
expect(component).toBeTruthy();
expect(component.version).toBeDefined();
done();
});
});
@Component({
selector: 'app-header',
template: ''
})
class MockHeaderComponent {
}
当我遇到这个问题时,我注意到控制台中出现以下消息:
如果“ngIf”是 Angular 控制流指令,请确保“NgIf”指令或“CommonModule”是声明此组件的 @NgModule 的一部分。
所以很可能,就像我的情况一样,感兴趣的
*ngIf
所在的组件尚未声明:
@NgModule({
imports: [
CommonModule,
FormsModule,
...
],
declarations: [
HeaderComponent // After adding the component the problem gets solved.
]
})