首页 > 解决方案 > 如何在茉莉花测试中模拟 RXJS timer()?

问题描述

我有一个角度组件来轮询新数据,当我们等待响应时,它每 X 秒更新一次 UI 中的消息。它循环显示一个简单的消息字符串数组。

一旦收到正确的数据,我们就会导航到相应的页面。

this.pollSubscription = timer(0, pollTimeInSeconds)
    .pipe(
        //convert each observable iteration into an interval in seconds
        map((count: number) => count * pollTimeInSeconds),
        //keep going if we are below the max poll time
        takeWhile((time: number) => time < this.maxPollTime),
        //update the UI message
        tap((time: number) => this.updateCurrentMessage(time)),
        //
        switchMap(() => this.getDataOrError$())
    )
    .subscribe(
        //navigate to the correct page
        (d: IData) => this.navigateBasedOnStatus(d),
        //If an error occurs, OR the observable completes (which should not happen), navigate to the error page
        () => this.navigateToError(),
        () => this.navigateToError()
    );

我想测试这种行为,但我不完全确定如何模拟timer这种情况。我看到了这个 SO 答案,但我无法根据我的情况来解决这个问题。

理想情况下,我想构建一个类似这样的测试,以确保显示每条消息,并且如果计时器比预期的时间长,它会循环回到第一条消息:

it('should show every status as the timer changes', fakeAsync(() => {
    tick(0);
    fixture.detectChanges();
    expect(debugEl.nativeElement.innerText.trim()).toEqual('Message one');

    tick(1000);
    fixture.detectChanges();
    expect(debugEl.nativeElement.innerText.trim()).toEqual('Message two');

    tick(2000);
    fixture.detectChanges();
    expect(debugEl.nativeElement.innerText.trim()).toEqual('Message three');

    //etc...
}));

编辑我正在根据下面的一些评论进行新的测试尝试,但这仍然不起作用

let timerTick: (milliseconds: number) => void;

beforeEach(() => {
    let fakeNow = 0;
    timerTick = (milliseconds: number): void => {
        fakeNow += milliseconds;
        tick(milliseconds);
    };
    asyncScheduler.now = (): number => fakeNow;
});

afterEach(() => {
    delete asyncScheduler.now;
});

it('should show every status as the timer changes', fakeAsync(() => {
    fixture.detectChanges(); // triggers ngOnInit()

    const pollTimeInSeconds = loginPollTime * 1000;
    let received: number | undefined;
    timer(0, pollTimeInSeconds, asyncScheduler).subscribe((value: number) => received = value);
    console.log(received);

    timerTick(0);
    fixture.detectChanges();
    expect(debugEl.nativeElement.innerText.trim()).toEqual('Message one');
    console.log(received)

    timerTick(pollTimeInSeconds);
    fixture.detectChanges();
    expect(debugEl.nativeElement.innerText.trim()).toEqual('Message two');
    console.log(received)

    timerTick(pollTimeInSeconds * 2);
    fixture.detectChanges();
    expect(debugEl.nativeElement.innerText.trim()).toEqual('Message three');
    console.log(received)
}));

茉莉花输出是:

Expected 'Message one' to equal 'Message two'.
Expected 'Message one' to equal 'Message three'.

控制台输出为:

> undefined
> 0
> 1
> 3

标签: jasminerxjskarma-jasminerxjs6

解决方案


推荐阅读