使用导入模块对 angular2 组件进行单元测试
Unit Testing angular2 component with imported module
我正在尝试在使用 angular-material2 的组件上编写测试,但是当我将它添加到我的 testModule 声明时,我得到:
Error: Template parse errors:
'md-card-title' is not a known element:
1. If 'md-card-title' is an Angular component, then verify that it is part of this module.
2. If 'md-card-title' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.
将 MaterialModule 添加到声明中会引发错误:模块
声明的意外模块 'MaterialModule'
DynamicTestModule' in config/spec-bundle.js (line 24994)
这是我的规范文件的样子:
beforeEach(() => TestBed.configureTestingModule({
declarations: [],
providers: [
{ provide: DataService, useValue: mockDataService },
{ provide: ActivatedRoute, useClass: MockActivatedRoute },
{ provide: Router, useValue: mockRouter },
CellViewComponent
]
}));
将 CellViewComponent
添加到声明数组会引发错误。
当您使用 TestBed.configureTestingModule
时,您正在为测试环境从头开始 创建一个模块。因此,您在实际应用程序中需要什么才能使 CellViewComponent
正常工作,您还需要在测试模块中对其进行配置。
在您的情况下,您缺少 Material 卡片组件。在应用程序中,您可能将 MaterialModule
或 MdCardModule
导入到您的 AppModule
中。所以你需要在测试模块中做同样的事情
beforeEach(() => TestBed.configureTestingModule({
imports: [ MaterialModule /* or MdCardModule */ ],
declarations: [ CellViewComponent ],
providers: [
{ provide: DataService, useValue: mockDataService },
{ provide: ActivatedRoute, useClass: MockActivatedRoute },
{ provide: Router, useValue: mockRouter },
]
}));
这是一个真正的问题:除了导入组件的选择器之外,您可以模拟所有内容。
有一个简单的方法。它允许避免导入模块,相反你可以禁用这种错误。
只需将此添加到您的模块中:
import { NO_ERRORS_SCHEMA } from '@angular/core';
...
TestBed.configureTestingModule({
schemas: [ NO_ERRORS_SCHEMA ],
...
是的,如果您想进行集成(而不是孤立的)测试,这将无济于事,但它非常适合孤立的测试。
不过,即使您决定导入一个模块,我认为导入带有所有已实现选择器的模拟模块可能更正确。
在测试我们的 Angular 应用程序组件时,我经常做的只是通过引用导入父模块。对于大多数用例,它已经足够或接近足够,如果您通过添加新的声明或导入更改组件,那么您无需担心更改测试文件,因为测试文件导入了父模块。
我只是更改模块以导入一些外部组件用于测试目的,但这种情况很少见。
正则测试初始化伪代码
beforeEach(() => TestBed.configureTestingModule({
declarations: [
ComponentA,
ComponentB
],
providers: [
CellViewComponent
]
}));
假设这个组件在一个模块中。我将声明对象放入一个变量中,以便同时在 ParentModule 和测试中使用。
export var ParentModuleArgs = {
declarations: [
ComponentA,
ComponentB
],
providers: [
CellViewComponent
]
};
@NgModule(parentModuleArgs)
export class ParentModule {}
然后,我没有将整个 Module 数组重写到测试组件中并且非常不干燥,而是这样做了。
beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));
如果我需要添加一些东西,那么我们可以在配置测试台之前添加它
let moduleArgs: NgModule = ParentModuleArgs;
moduleArgs.providers.push({provide: APP_BASE_HREF, useValue: '/'});
beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));
我正在尝试在使用 angular-material2 的组件上编写测试,但是当我将它添加到我的 testModule 声明时,我得到:
Error: Template parse errors:
'md-card-title' is not a known element:
1. If 'md-card-title' is an Angular component, then verify that it is part of this module.
2. If 'md-card-title' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.
将 MaterialModule 添加到声明中会引发错误:模块
声明的意外模块 'MaterialModule'DynamicTestModule' in config/spec-bundle.js (line 24994)
这是我的规范文件的样子:
beforeEach(() => TestBed.configureTestingModule({
declarations: [],
providers: [
{ provide: DataService, useValue: mockDataService },
{ provide: ActivatedRoute, useClass: MockActivatedRoute },
{ provide: Router, useValue: mockRouter },
CellViewComponent
]
}));
将 CellViewComponent
添加到声明数组会引发错误。
当您使用 TestBed.configureTestingModule
时,您正在为测试环境从头开始 创建一个模块。因此,您在实际应用程序中需要什么才能使 CellViewComponent
正常工作,您还需要在测试模块中对其进行配置。
在您的情况下,您缺少 Material 卡片组件。在应用程序中,您可能将 MaterialModule
或 MdCardModule
导入到您的 AppModule
中。所以你需要在测试模块中做同样的事情
beforeEach(() => TestBed.configureTestingModule({
imports: [ MaterialModule /* or MdCardModule */ ],
declarations: [ CellViewComponent ],
providers: [
{ provide: DataService, useValue: mockDataService },
{ provide: ActivatedRoute, useClass: MockActivatedRoute },
{ provide: Router, useValue: mockRouter },
]
}));
这是一个真正的问题:除了导入组件的选择器之外,您可以模拟所有内容。
有一个简单的方法。它允许避免导入模块,相反你可以禁用这种错误。
只需将此添加到您的模块中:
import { NO_ERRORS_SCHEMA } from '@angular/core';
...
TestBed.configureTestingModule({
schemas: [ NO_ERRORS_SCHEMA ],
...
是的,如果您想进行集成(而不是孤立的)测试,这将无济于事,但它非常适合孤立的测试。
不过,即使您决定导入一个模块,我认为导入带有所有已实现选择器的模拟模块可能更正确。
在测试我们的 Angular 应用程序组件时,我经常做的只是通过引用导入父模块。对于大多数用例,它已经足够或接近足够,如果您通过添加新的声明或导入更改组件,那么您无需担心更改测试文件,因为测试文件导入了父模块。
我只是更改模块以导入一些外部组件用于测试目的,但这种情况很少见。
正则测试初始化伪代码
beforeEach(() => TestBed.configureTestingModule({
declarations: [
ComponentA,
ComponentB
],
providers: [
CellViewComponent
]
}));
假设这个组件在一个模块中。我将声明对象放入一个变量中,以便同时在 ParentModule 和测试中使用。
export var ParentModuleArgs = {
declarations: [
ComponentA,
ComponentB
],
providers: [
CellViewComponent
]
};
@NgModule(parentModuleArgs)
export class ParentModule {}
然后,我没有将整个 Module 数组重写到测试组件中并且非常不干燥,而是这样做了。
beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));
如果我需要添加一些东西,那么我们可以在配置测试台之前添加它
let moduleArgs: NgModule = ParentModuleArgs;
moduleArgs.providers.push({provide: APP_BASE_HREF, useValue: '/'});
beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));