使用 ngIf 异步管道可观察到的 Jasmine 大理石测试
Jasmine marble testing observable with ngIf async pipe
我想用 jasmine-marble 测试来测试 Observable
,但遗憾的是我不知道如何触发 ngIf
的变化检测,这应该会渲染组件。
这是我的class的简化版本:
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
。
您的订阅是异步的。这意味着您的 console.log
可以在最后一个 expect
之后触发。在您最后期望数据可能尚未加载,因此该值未定义。
使用 tick(100)
而不是 tick()
可能会奏效。请注意,这会使您的测试慢 100 毫秒。
您也可以切换到异步并等待可观察到 return 一个值:
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();
}));
我通过创建另一个测试套件解决了这个问题,我在其中手动为可观察对象定义了一个值。我对这种方法不是很满意,但它是解决我的问题的方法。
我想用 jasmine-marble 测试来测试 Observable
,但遗憾的是我不知道如何触发 ngIf
的变化检测,这应该会渲染组件。
这是我的class的简化版本:
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
。
您的订阅是异步的。这意味着您的 console.log
可以在最后一个 expect
之后触发。在您最后期望数据可能尚未加载,因此该值未定义。
使用 tick(100)
而不是 tick()
可能会奏效。请注意,这会使您的测试慢 100 毫秒。
您也可以切换到异步并等待可观察到 return 一个值:
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();
}));
我通过创建另一个测试套件解决了这个问题,我在其中手动为可观察对象定义了一个值。我对这种方法不是很满意,但它是解决我的问题的方法。