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

Angular中combineLatest结合Jest测试问题:pipe未触发

Angular Jest测试中combineLatest未触发的问题解决

问题场景

Angular组件中通过combineLatest组合两个Observable,运行应用时逻辑正常,但Jest测试里调用updateGridSubject.next(true)后,pipe内的逻辑未触发,导致erinnerungService的调用及erinnerungen数据赋值都没生效。

组件代码

export class ErinnerungenErinnerungenComponent implements OnInit, OnDestroy {    

...

erinnerungen: ErinnerungModel[] = [];

ErinnerungData$ = combineLatest([
this.featureSessionStoreService.auftragIdLookupModelSubject,
this.updateGridSubject]).pipe
(
  tap(() => this.loadingGridSubject.next(true)),
  switchMap(() =>
    this.erinnerungService.getErinnerungenForAuftrag(
      this.featureSessionStoreService.auftragIdLookupModel as GetErinnerungenForAuftrag
    )
  ),
  tap((erinnerungenModel) => {
    this.erinnerungen = erinnerungenModel.erinnerungen;
  }),
  tap(() => this.loadingGridSubject.next(false)),
  takeUntil(this.componentIsDestroyed$)
  )
.subscribe();


constructor(...) {}

ngOnInit() {...}

}

原测试代码

it('should get Erinnerungen for Auftrag from Backend', () => {
component.updateGridSubject.next(true);

expect(erinnerungService.getErinnerungenForAuftrag).toHaveBeenCalled();
expect(component.erinnerungen.length).toBeGreaterThan(0);
});

问题原因

  1. combineLatest触发条件未满足:combineLatest要求所有输入的Observable都至少发出过一次值,才会向下游推送数据。测试环境中auftragIdLookupModelSubject默认没有发出过值,所以仅调用updateGridSubject.next(true)无法触发pipe逻辑。
  2. 异步操作未等待:Observable的操作是异步的,原测试没有等待异步流程完成就执行断言,导致断言在逻辑生效前就运行。

修复后的测试代码

import { fakeAsync, tick } from '@angular/core/testing';
import { of } from 'rxjs';

// ... 其他导入和测试配置

it('should get Erinnerungen for Auftrag from Backend', fakeAsync(() => {
  // 1. 模拟auftragIdLookupModelSubject发出有效值,并赋值组件依赖的属性
  const mockAuftrag = { id: 123 } as GetErinnerungenForAuftrag;
  featureSessionStoreService.auftragIdLookupModelSubject.next(mockAuftrag);
  featureSessionStoreService.auftragIdLookupModel = mockAuftrag;

  // 2. mock erinnerungService的返回值,返回同步Observable
  const mockErinnerungenList = [
    { id: 1, title: '测试提醒' } as ErinnerungModel
  ];
  jest.spyOn(erinnerungService, 'getErinnerungenForAuftrag')
      .mockReturnValue(of({ erinnerungen: mockErinnerungenList }));

  // 3. 触发更新信号
  component.updateGridSubject.next(true);
  // 4. 触发异步流程完成
  tick();

  // 5. 执行断言
  expect(erinnerungService.getErinnerungenForAuftrag).toHaveBeenCalledWith(mockAuftrag);
  expect(component.erinnerungen).toEqual(mockErinnerungenList);
}));

关键修复点

  • 确保combineLatest的两个输入Observable都发出过值:测试前给auftragIdLookupModelSubject发送模拟数据。
  • 处理异步逻辑:用fakeAsync和tick来等待Observable的异步操作完成,保证断言在逻辑执行后运行。
  • 正确mock服务返回:让getErinnerungenForAuftrag返回一个同步的Observable(用of()),确保流程能走完。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:00:30