Sas*_*sha 6 angular angular-test
只想说,我认识到有很多与“无法绑定到 X,因为它不是 Y 的已知属性”错误相关的 SO 帖子。我查看了大量答案,并找到了许多解决特定问题的答案,但我无法将其转换为我的案例,实际上我认为这很笼统,并且与对我应该如何解决我的用例。
我正在创建一个 Angular (7) 应用程序,我已将其分为components和routes。该components是模块化件(下拉菜单,情态动词,按钮,等等),这些路由的应用程序单独的页面。这个术语有点复杂,因为两者在技术上都是 Angular 组件。换句话说,结构(内src/)看起来像这样:
- app
- components
- dropdown
- dropdown.component.ts
- dropdown.component.html
- dropdown.component.scss
- dropdown.component.spec.ts
- routes
- library
- library.component.ts
- library.component.html
- library.component.scss
- library.component.spec.ts
...
Run Code Online (Sandbox Code Playgroud)
所以我有一个 Library 路由,它只是一个 Angular 组件,它导入一个 Dropdown 组件,如下所示:
import { Component, OnInit } from '@angular/core';
import { DropdownComponent } from '../../components/dropdown/dropdown.component';
@Component({
selector: 'app-library',
templateUrl: './library.component.html',
styleUrls: ['./library.component.scss']
})
export class LibraryComponent implements OnInit {
pickItem($event) {
console.log($event.item, $event.index);
}
constructor() { }
ngOnInit() {}
}
Run Code Online (Sandbox Code Playgroud)
相关的库 HTML 文件:
<div class="library row py4">
<h3 class="typ--geo-bold typ--caps mb5">Style Library</h3>
<div class="mb4" style="max-width: 35rem;">
<p class="typ--geo-bold typ--caps">Dropdowns</p>
<app-dropdown
[items]="['One', 'Two', 'Three']"
(pick)="pickItem($event)"
title="Default dropdown"
></app-dropdown>
<br />
<app-dropdown
[items]="['One', 'Two', 'Three']"
(pick)="pickItem($event)"
title="Inline dropdown"
class="dropdown--inline"
></app-dropdown>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
下拉组件是一个基本组件,遵循类似的结构。除非被问到,否则我不会将它粘贴在这里,因为我不确定它是否会添加。(可以说它确实接受items作为输入 - 与以下错误相关)就足够了。
这在浏览器中完美运行,并在生产中正确构建。
library.components.spec.ts但是,当我运行测试时,遇到以下错误:
Failed: Template parse errors:
Can't bind to 'items' since it isn't a known property of 'app-dropdown'.
1. If 'app-dropdown' is an Angular component and it has 'items' input, then verify that it is part of this module.
2. If 'app-dropdown' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
<p class="typ--geo-bold typ--caps">Dropdowns</p>
<app-dropdown
[ERROR ->][items]="['One', 'Two', 'Three']"
(pick)="pickItem($event)"
title="Default dropdown"
Run Code Online (Sandbox Code Playgroud)
这是基本的库规范文件:
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { LibraryComponent } from './library.component';
describe('LibraryComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [LibraryComponent],
}).compileComponents();
}));
it('should create the component', () => {
const fixture = TestBed.createComponent(LibraryComponent);
const lib = fixture.debugElement.componentInstance;
expect(lib).toBeTruthy();
});
});
Run Code Online (Sandbox Code Playgroud)
Library 组件和 Dropdown 组件都没有关联的模块。我的理解是,这个错误可能与我没有将 Dropdown 组件导入到库模块中的事实有关,但
有没有办法让测试工作而不将这些组件转换为模块?所有路由组件都应该是模块吗?
编辑
添加下拉组件(如果相关):
<div
class="dropdown"
[ngClass]="{ open: open }"
tab-index="-1"
[class]="class"
#dropdown
>
<div class="dropdown__toggle" (click)="onTitleClick(dropdown)">
<span class="dropdown__title">{{ finalTitle() }}</span>
<span class="dropdown__icon icon-arrow-down"></span>
</div>
<div *ngIf="open" class="dropdown__menu">
<ul>
<li
*ngFor="let item of items; let ind = index"
class="dropdown__item"
[ngClass]="{ selected: selectedIndex === ind }"
(click)="onItemClick(dropdown, item, ind)"
>
<span class="dropdown__label">{{ item }}</span>
</li>
</ul>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
和:
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.scss']
})
export class DropdownComponent implements OnInit {
@Input() items: Array<string>;
@Input() public selectedIndex: number = null;
@Input() public title = 'Select one';
@Input() public open = false;
@Input() public class = '';
@Output() pick = new EventEmitter();
constructor() { }
ngOnInit() {}
finalTitle () {
return typeof this.selectedIndex === 'number'
? this.items[this.selectedIndex]
: this.title;
}
onItemClick(dropdown, item, index) {
this._blur(dropdown);
this.selectedIndex = index;
this.open = false;
this.pick.emit({ item, index });
}
onTitleClick(dropdown) {
this._blur(dropdown);
this.open = !this.open;
}
_blur(dropdown) {
if (dropdown && dropdown.blur) { dropdown.blur(); }
}
}
Run Code Online (Sandbox Code Playgroud)
A)有很多方法可以在不创建新模块的情况下完成此任务。您可以简单地将 DropdownComponent 导入到您的测试模块中,如下所示 Andr\xc3\xa9 建议的那样。我在这个答案中概述了下面的另一种方法,该方法存根 DropdownComponent,只是为了测试 LibraryComponent。希望这能回答“如何做到这一点”的问题。
\n\nB)我建议的存根不是一个模块——它甚至不是一个组件。无需将存根合并到整个应用程序中,它的唯一目的是测试 LibraryComponent。
\n\nC)这个存根的价值只是为了测试 LibraryComponent,这就是为什么最好让它尽可能简单。
\n\n这是无需将组件转换为模块即可进行测试的一种方法。
\n\n下面是一种对您尝试在 LibraryComponent 内部使用的 DropdownComponent 进行存根的方法。您在问题中详细说明的错误与您没有定义“app-dropdown”选择器但您的 LibraryComponent 正在尝试绑定到它这一事实直接相关。假设您只想测试library.component.spec.ts 文件中的LibraryComponent,我建议对DropdownComponent 功能进行存根处理,而不是将实际组件导入到测试中。我创建了一个Stackblitz来展示我的意思。
\n\n以下是来自 Stackblitz 的library.component.spec.ts 文件的片段:
\n\n@Component({\n selector: \'app-dropdown\',\n template: `<h5>Dropdown</h5>`\n})\nclass TestDropdownComponent {\n @Input() items;\n @Input() title;\n @Output() pick = new EventEmitter<any>();\n}\n\ndescribe(\'LibraryComponent\', () => {\n let component: LibraryComponent;\n let fixture: ComponentFixture<LibraryComponent>;\n\n beforeEach(async(() => {\n TestBed.configureTestingModule({\n imports: [ RouterTestingModule ],\n declarations: [ \n TestDropdownComponent,\n LibraryComponent\n ]\n }).compileComponents();\n fixture = TestBed.createComponent(LibraryComponent);\n }));\n it(\'should create the component\', () => {\n const fixture = TestBed.createComponent(LibraryComponent);\n const lib = fixture.debugElement.componentInstance;\n expect(lib).toBeTruthy();\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n注意 - 如果您想重现您在 Stackblitz 中的问题中详细说明的错误,只需注释掉 TestBed 声明中的 TestDropdownComponent 行,使其看起来像这样:
\n
TestBed.configureTestingModule({\n imports: [ RouterTestingModule ],\n declarations: [ \n // TestDropdownComponent,\n LibraryComponent\n ]\n}).compileComponents();\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n您将再次只测试您的组件,而无需绑定 DropdownComponent 的模拟/存根。
\n
| 归档时间: |
|
| 查看次数: |
7033 次 |
| 最近记录: |