1

我想Observable用 jasmine-marble 测试测试一个,但不幸的是我不知道如何触发更改检测ngIf,这应该呈现组件。

这是我的课程的简化版本:

export class MyComponent implements OnInit {
  data$: Observable<{data: any[]}>;

  constructor(private baseService: BaseService) { }

  ngOnInit(): void {
    this.data$ = this.baseService.get(endpoint);
  }
}

还有我的html文件:

<custom-component *ngIf="data$ | async as value" [data]="value.data">
    ...
</custom-component>

这是我当前的测试,失败了:

it ('should display custom component', fakeAsync(() => {
    const expected = cold('a|',  {a: {data: [{id: 1}]}});
    baseServiceStub.get.and.returnValue(expected);
    component.ngOnInit();
    fixture.detectChanges();
    tick();
    expect(component.data$).toBeObservable(expected); // this passes and the observable also holds the correct value
    expect(baseService.get).toHaveBeenCalledWith(endpoint); // this passes aswell
    component.data$.subscribe(val => {
      console.log(val); // here I can log the correct value of the observable ( {data: [{id:1}]})
    });
    expect(fixture.debugElement.query(By.css('custom-component'))).not.toBeNull(); // this fails
}));

不幸的是我得到的都是这个

Error: Expected null not to be null.

服务或可观察对象本身没有问题,但在我看来,由于某种原因,DOM 不会触发使用异步管道来渲染组件的更改检测。

PS:当我使用时,getTestScheduler().flush()我得到了错误Can't subscribe to undefined

4

2 回答 2

0

您的订阅是异步的。这意味着你console.log可以在你最后一个之后开火expect。在您最后的期望中,数据可能尚未加载,因此该值未定义。

使用tick(100)而不是tick()可能会起作用。请注意,这将使您的测试慢 100 毫秒。

你也可以切换到 async 并等待 observable 返回一个值:

it ('should display custom component', async(() => {
    ...
    // tick(); //dont call this
    ...
    await component.data$.pipe(take(1)).toPromise()
    expect(fixture.debugElement.query(By.css('custom-component'))).not.toBeNull(); 
}));
于 2021-04-15T19:39:19.513 回答
0

我通过创建另一个测试套件解决了这个问题,我在其中手动定义了 observable 的值。我对这种方法并不完全满意,但它是我的问题的解决方法。

于 2021-04-19T07:40:02.293 回答