对服务中的BehaviorSubject进行单元测试

时间:2020-05-22 12:22:13

标签: angular unit-testing rxjs

我正在研究一个玩具项目,以学习Angular中的单元测试(用Jest代替了Karma)。我见过类似的问题,但所有问题对订阅的处理方式都不一样,因此我无法获得确切的答案来为我工作。

TL; DR:我正在尝试测试BehaviorSubject,但是它不是我期望的值,而是向我发送的初始值。我了解测试中订阅的顺序很重要,但是我还无法确定正确的顺序。

我在服务中有一个BehaviorSubject:

export class SomeService {
  // ...
  remainingSeconds: number;

  private _seconds: Subject<number> = new BehaviorSubject(RegularTimerSeconds.WORK_TIME);
  public readonly seconds$: Observable<number> = this._seconds.asObservable();

  setTimer(seconds: number) {
    this.remainingSeconds = seconds;
    this._seconds.next(this.remainingSeconds);
  }

  // ...
}

和组件上的侦听器,该组件使用模板中的异步管道订阅了Observable

export class SomeComponent implements OnInit, OnDestroy {
  // ...
  remainingSeconds$ = this.timer.seconds$.pipe(tap(seconds => console.log(`remainingSeconds$: ${seconds}`)));

  constructor(public timer: TimerService) {}
}

订阅在模板中进行如下

<ng-container *ngIf="{
  remainingSeconds: remainingSeconds$ | async,
  currentState: currentState$ | async,
  informationText: informationText$ | async,
  doneCounter: doneCounter$ | async
} as data">
  <!-- ... -->
  <div class="regular-timer-container" *ngIf="data.remainingSeconds !== undefined">
    <p>Remaining seconds: {{ data.remainingSeconds }}</p>  
  </div>
</ng-container>

我想测试一下,当调用服务中的setTimer函数时,组件中可观察到的剩余Seconds $是否也获得了正确的值。尤其是,如果未定义服务中的“ remainingSeconds”值,则我想确保ObservableSeconds $ observable获取更新后的未定义值,并因此隐藏了适当的UI元素。

测试遇到的问题(代码如下)是,当我从组件调用service.setTimer(undefined)时,我得到的是BehaviorSubject的初始值,而不是{{1 }}我想要的值(这使测试无用)。

undefined

我要添加a stackblitz link,但是很遗憾,我无法在该处运行npm test。希望它将对我要完成的工作给出一些基本的想法。

2 个答案:

答案 0 :(得分:1)

您可以使用以下方法快速解决此问题:

component.remainingSeconds$.pipe(skip(1)).subscribe(...)

答案 1 :(得分:0)

尝试

TestBed.configureTestingModule({
        declarations: [
          AppComponent
        ],
        providers: [
          TimerService
        ]
      }).compileComponents();

并删除TestBed.inject

相关问题