Angular 模拟可观测不返回值的角度单元测试
我的组件返回基于小时的当前班次Angular 模拟可观测不返回值的角度单元测试,angular,Angular,我的组件返回基于小时的当前班次 export class CurrentTimeComponent { constructor() {} now$: Observable<Date> = timer(0, 1000).pipe( map(() => new Date()), share() ); shift$: Observable<string> = this.now$.pipe( map((now) => {
export class CurrentTimeComponent {
constructor() {}
now$: Observable<Date> = timer(0, 1000).pipe(
map(() => new Date()),
share()
);
shift$: Observable<string> = this.now$.pipe(
map((now) => {
const hour = now.getHours();
if (hour < 13) {
return 'early';
} else if (hour < 20) {
return 'late';
} else {
return 'night';
}
})
);
}
但是,当我调试测试时,
shift$
总是返回当前日期。它是否应该返回我提供的模拟组件(parseISO(…)?问题在于,组件实例化时会创建可观察的shift$
。创建时,它使用创建时的this.now$
值,这是now$
初始化为的计时器
因此,在您的测试中,当您重新定义组件时。现在$
成为一个不同的可观察对象,已经构建了shift$
可观察链,它引用了原始的计时器
可观察对象
为了解决这个问题(假设您可以更新组件代码),您可以使用将shift$
可观察值的创建推迟到订阅时,而不是组件实例化时:
shift$:Observable=defer(()=>this.now$.pipe(/){
const hour=now.getHours();
如果(小时<13){
提前返回;
}否则,如果(小时<20){
返回“晚”;
}否则{
返回“夜晚”;
}
})
));
在订阅shift$
之前,传递给defer
的工厂函数将不会执行。这样,this.now$
在您订阅shift$
之前将不会被引用,因此在订阅shift$
之前,您将有机会在测试中重新定义now$
展示这种方法。(打开控制台以验证测试中定义的日期是否为实际接收的日期。)thx用于您的解决方案。奇怪的是,我认为这无关紧要,因为在创建时,我没有订户,而且两个都是冷的可观察对象。在您订阅它们之前,它们不会开始发出值,但可观察对象本身已经创建。如果你把它们仅仅看作物体,可能会更清楚this.now$.pipe()
只返回一个对象(恰好是一个可观察对象),因此当您说shift$=this.now$.pipe()
时,您将立即执行该pipe()
方法并将其返回值分配给shift$
。如果您随后将now$
重新分配给其他对象,这不会影响shift$
,因为shift$
已经分配,它不会在订阅时重新执行this.now$.pipe()
。是的,迈克。谢谢你的帮助:)
it('should get late shift', (done) => {
component.now$ = of(parseISO('2021-04-01T16:00:00Z'));
component.shift$.subscribe((shift) => {
expect(shift).toEqual('late');
done();
});
});