You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 19升级后RxJS interval单元测试行为异常问题

Angular 19 升级后定时器单元测试多一次emit的原因分析

我有一个Angular 18服务,通过每分钟更新BehaviorSubject来追踪时间,简化代码如下:

private totalDurationMin = 0;
private totalDurationMinutesSubject$ = new BehaviorSubject(this.totalDurationMin);
public totalDurationMinutes$ = this.totalDurationMinutesSubject$.asObservable();

public clockIn(): void {
  this.startTimer(0);
}

private startTimer(startingMinutes: number): void {
  this.totalDurationMin = startingMinutes;
  this.totalDurationMinutesSubject$.next(this.totalDurationMin);

  this.timerSubscription = interval(60 * 1000).subscribe({
    next: () => {
      this.totalDurationMin++;
      this.totalDurationMinutesSubject$.next(this.totalDurationMin);
    }
  });
}

对应的单元测试代码:

it('should update the observables and start the timer when clocking in', fakeAsync(() => {
  //skip initial emit, the start of the timer, and then then next 4 minute ticks
  service.totalDurationMinutes$.pipe(skip(6)).subscribe({
    next: (val) => {
      console.log(`minutes: ${val}`);
      expect(val).toEqual(5);
    },
  });

  service.clockIn();
  tick(60 * 1000 * 5); //simulate 5 minutes passing
}));

该测试在Angular 18中可正常通过,但升级到Angular 19后,测试会多一次emit——断言期望5却得到6。调试日志显示Angular 18中仅输出minutes:5,Angular 19中输出minutes:5和minutes:6。目前添加take(1)可让测试通过,想了解导致该变化的原因。


原因分析

这一变化源于Angular 19配套升级的RxJS 8.x对interval在fakeAsync环境下的调度逻辑调整:

  • 在Angular 18对应的RxJS 7.x中,fakeAsync的tick(ms)只会触发到达指定时间点前的所有调度任务;
  • 升级到RxJS 8.x后,interval的触发时机被调整,当调用tick(300000)(模拟5分钟)时,会刚好触发第5次计时结束后的emit,同时额外触发第6次计时的emit——因为RxJS 8的定时器调度会在时间点到达时,执行一次额外的调度循环。

具体emit次数拆解:

  1. BehaviorSubject初始值0(第1次)
  2. clockIn()调用后startTimer立即发射0(第2次)
  3. 第1分钟:发射1(第3次)
  4. 第2分钟:发射2(第4次)
  5. 第3分钟:发射3(第5次)
  6. 第4分钟:发射4(第6次)
  7. 第5分钟:发射5(第7次)
  8. RxJS 8中tick(300000)额外触发第6分钟的发射6(第8次)

测试中skip(6)会跳过前6次emit,在Angular 18中仅能接收到第7次的5;而Angular 19中会同时接收到第7次的5和第8次的6,导致断言失败。添加take(1)可以限定只取第一个符合条件的emit,从而让测试通过。

内容的提问来源于stack exchange,提问作者Chris Barr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:34:57