我正在尝试为修改 Angular CDK 表的指令编写测试。为了测试这一点,我在 *.spec.ts 文件中添加了一个测试组件,在其中设置了一个简单的表格并添加了我的指令。
但是,在运行时,在fixture.detectChanges() 上,组件会抛出两个错误。一是输入属性未知,二是来自指令,未设置所需的输入。
Can't bind to 'sortableColumns' since it isn't a known property of 'table' (used in the 'TestComponent' component template)
ERROR RuntimeError: NG0950: Input is required but no value is available yet.
测试组件看起来像这样(为了简洁,我删除了一些逻辑):
@Component({
standalone: true,
imports: [CdkTableModule, SortableTableDirective],
template: ` <table cdk-table sortableTable [dataSource]="dataSource" [sortableColumns]="sortableColumns">
<ng-container cdkColumnDef="columnA">
<th cdk-header-cell *cdkHeaderCellDef>The First Column</th>
<td cdk-cell *cdkCellDef="let element">{{ element.columnA }}</td>
</ng-container>
<ng-container cdkColumnDef="columnB">
<th cdk-header-cell *cdkHeaderCellDef>The Second Column</th>
<td cdk-cell *cdkCellDef="let element">{{ element.columnB }}</td>
</ng-container>
<ng-container cdkColumnDef="columnC">
<th cdk-header-cell *cdkHeaderCellDef>The Third Column</th>
<td cdk-cell *cdkCellDef="let element">{{ element.columnC }}</td>
</ng-container>
<tr cdk-header-row *cdkHeaderRowDef="displayedColumns"></tr>
<tr cdk-row *cdkRowDef="let row; columns: displayedColumns"></tr>
</table>`,
})
class TestComponent {
dataSource = //data-source creation etc removed for brevity
sortableColumns = ['columnA', 'columnB'];
displayedColumns = ['columnA', 'columnB', 'columnC'];
}
测试设置如下。尽管在夹具设置上抛出错误,但表变量仍获得一个值。然而,当我稍后想检查该指令是否已运行时,它没有运行。我尝试过使用和不使用compileComponents函数,它没有什么区别。
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SortableTableDirective, TestComponent, CdkTableModule],
}).compileComponents();
fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
table = fixture.debugElement.query(By.directive(SortableTableDirective));
});
从依赖的角度来看,指令本身相当简单,不依赖于一些核心角度之外的任何东西
@Directive({
selector: 'table[sortableTable]',
standalone: true,
})
export class SortableTableDirective<T> implements OnDestroy {
dataSource = input.required<SortableDatasource<T>>();
sortableColumns = input.required<string[]>();
public constructor(
private renderer: Renderer2,
private elRef: ElementRef,
private containerRef: ViewContainerRef,
) {
// code removed
}
cdk-table 指令按其应有的方式工作和运行,其创建的元素在夹具中均可用。代码“实时”运行得非常好。
编辑: 进一步的测试似乎表明问题出在信号输入上。用@Input替换信号输入解决了绑定问题。目前尚不清楚这是一个错误还是我做错了什么。
编辑2: 我们使用 jest 来运行测试。使用 karma + jasmine 似乎也适用于我尝试制作的最小复制项目。
通过这个github问题找到答案https://github.com/angular/angular/issues/54013
简而言之:我们使用的 jest-preset-Angular 版本已经过时,并且没有使用正确的 JIT 转换。更新到 14.0.3 解决了该问题,现在大多数测试都可以正常运行。