【发布时间】:2018-11-18 10:41:40
【问题描述】:
我们最近从 Angular 5 更新到了 Angular 6,以及 RxJs 6。 作为迁移的一部分,计时器的使用已从:
Observable.timer()
到
timer()
在我们的测试中有很多地方我们使用以下模式模拟计时器可观察对象。
let timerObserver: Observer<any>;
beforeEach(() => {
spyOn(Observable, 'timer').and.returnValue(Observable.create(
((observer: Observer<any>) => {
timerObserver = observer;
})
));
});
it(`should not have any notifications by default`, () => {
timerObserver.next('');
...
});
有人知道如何迁移这种模式吗?
编辑:我在这里创建了问题的简化说明:
https://stackblitz.com/edit/angular-v6-testing-template-nm7add
// Hello.Component
ngOnInit() {
const timer$ = timer(30);
timer$.subscribe(() => {
this.testMe = 'this has been changed';
});
}
// Hello.component.spec
it('should set testMe after a given timer', fakeAsync(() => {
tick(50);
expect(fixture.componentInstance.testMe).toBe('this has been changed');
}));
在这个例子中,我试图让计时器触发而不等待计时器解决。
【问题讨论】:
-
请改用
VirtualTimeScheduler。见this answer。或者——甚至更好——使用marble test。 -
感谢您的回复卡坦特。如果我理解正确,我可以使用 VirtualTimeScheduler 在我的规范中创建计时器可观察对象,但我想做的是模拟在我的组件中创建的计时器,因此我无法直接访问它。
-
好的,如果你使用
fakeAsync,你可以依赖它来模拟setInterval——这是RxJS在它的AsyncScheduler中使用的——但是你需要破坏asyncScheduler的now方法返回fakeAsync的当前时间概念。有关破坏机制,请参阅this answer。 (虽然,async现在被命名为asyncScheduler。)未破坏的,now将被称为Date.now()和 that won't work 和fakeAsync。