QueryList.changes.subscribe()在Angular单元测试中不会被触发 &g



我想根据收到的项目数量为弹出窗口生成一些容器。组件在开发和生产中按预期工作,但在单元测试中没有工作,因为查询列表。变化永远不会发生。我必须调用querylist.notifyChanges()作为变通方法。mapRef是一个Openlayers映射实例

HTML模板:

<ng-container *ngFor="let id of currentDivs">
<div class="popup" #popupContainer [id]="id"></div>
</ng-container>

组件:

@ViewChildren("popupContainer", { read: ElementRef })
popupContainers: QueryList<ElementRef<HTMLElement>>;
ngOnInit(): void {
//init map and other stuff...
init();
}
ngAfterViewInit(): void {
this.popupContainers.changes.subscribe(
(containers: QueryList<ElementRef>) => {
this._mapRef.getOverlays().clear();
containers.forEach((container) => {
//create overlay container for popup
const id = container.nativeElement.id;
if (!this._mapRef.getOverlayById(id)) {
const overlay = new Overlay({
id,
element: container.nativeElement,
autoPan: false,
});
this._mapRef.addOverlay(overlay);
}
});
}
);
}
init(): void {

bService.getItems().subscribe((items) => {
this.ngZone.runOutsideAngular(() => {
divs = items.map((item) =>item.id);
this.ngZone.run(() => {
this.currentDivs = divs;
this.cdr.detectChanges();
});
});
});
}

测试代码:

beforeEach((done) => {
aServiceSpy.getInfo.and.returnValue(of(infos));
bServiceSpy.getItems.and.returnValue(of(items));
fixture.detectChanges();
component.mapRef.once("rendercomplete", () => {
//I have to call notifyChanges() as a workaround 
//component.popupContainers.notifyChanges() 
done();
});
it("should populate popup",() => {
console.log(component.popupContainers) 
// it actually has length == items.length,
//but component.popupContainers.changes in the actual code never emit
})
});

在Angular单元测试中,当QueryList发生变化时,应该自动调用querylist.changes。有几件事需要注意

  1. 确保初始化后有查询的内容更改。看来你的考试内容从未改变过。您可以添加this.popupContainers.changes.pipe(startWith(this.popupContainers))以始终初始化订阅。
  2. 我没有看到你的代码有任何计时器停止queryList的变化,只是分享我的经验在这里。我在我的内容查询订阅中有一个delay(0),我在测试之前运行detectChanges,这实际上导致测试在订阅发出之前结束。所以我把changeDetection放进fakeAsync进程解决了我的问题。
beforeEach(() => {
// Create component etc initialize
fixture.detectChanges(); 
});
describe('test', fakeAsync(() => {
// Test logic
}));

beforeEach(() => {
// Create component etc initialize
});
describe('test', fakeAsync(() => {
fixture.detectChanges(); 
// Test logic
}));

最新更新