如何使用 jasmine marbels 对可观察的计时器()进行单元测试

问题描述 投票:0回答:1

我正在尝试在角度应用程序中对 ngrx 效果进行单元测试,该效果使用计时器引入一些轮询逻辑,并根据某些选择器的值映射到一些操作。

我的代码是这样的:

@Injectable()
export class YourEffects {
  timerEffect$ = createEffect(() =>
    this.actions$.pipe(
      ofType(fromActions.startTimerAction),
      switchMap(() =>
        timer(0, 1000).pipe(
          withLatestFrom(this.store.select(selectCondition)),
          map(() => {
            if (condition) {
              return fromActions.timerTickAction1()
            }

            return fromActions.timerTickAction2()
          })
        )
      )
    )
  );

  constructor(private actions$: Actions) {}
}

我成功地用

fakeAsync
使用这种方法对此进行了单元测试,但在使用 Jasmine Marbels 时遇到了麻烦

尝试像这样和茉莉一起转移时间

it('should emit timerTickAction every second', () => {
  // Arrange
  store.overrideSelector(selectCondition, someFalsyValue);
  const startAction = fromActions.startTimerAction();
  const tickAction = fromActions.timerTickAction2();

  // Act
  actions = hot('-a', { a: startAction });

  // Use jasmine.clock().install() to control the passage of time
  jasmine.clock().install();

  // Simulate the passage of time and test the effect
  jasmine.clock().tick(1000); // 1 second
  const expected = cold('-b', { b: tickAction });

  // Assert
  expect(effects.timerEffect$).toBeObservable(expected);

  // Clean up the clock
  jasmine.clock().uninstall();
});

如果有人能建议使用弹珠进行测试的方法,我将非常感激。谢谢!

angular unit-testing rxjs observable ngrx
1个回答
0
投票

从我自己的一些测试中,我发现使用

jasmine-marbles
我可以使用
timer
interval
来测试可观察量,前提是它们在
TestScheduler.run()
回调中运行。我无法找到为什么会这样的彻底解释。

另一点是,在编写弹珠测试时,您必须在某个时刻完成您的可观察量。有时就像

timer
interval
的情况一样,如果在源代码或测试设置中没有传递完成机制,则可观察对象永远不会完成,并且测试将因此无法工作。这在
rxjs
仓库的本期中提到:https://github.com/ReactiveX/rxjs/issues/3957

另请查看这篇关于大理石测试的文档:https://rxjs.dev/guide/testing/marble-testing#time-progression-syntax。 这将解释为什么在我们的弹珠中我们使用

999ms
而不是
1s

考虑到所有这些,这就是我测试您的效果代码的方式:

it('should emit twice, on start and after 1s', () => {
  // given
  store.overrideSelector(selectCondition, someFalsyValue);
  const startAction = fromActions.startTimerAction();
  const tickAction = fromActions.timerTickAction2();

  const scheduler = getTestScheduler();
  scheduler.run(() => {
    // when
    actions$ = hot('a', {
      a: startAction
    });

    // then
    const expected = cold('a 999ms (a |)', {
      a: tickAction
    });
    expect(effects.timerEffect$.pipe(take(2))).toBeObservable(expected);
  });
});

getTestScheduler()
是从
jasmine-marble
导入的,
hot
cold
相同。

如果使用

take(3)
而不是
take(2)
,你的输出大理石应该看起来像这样
a 999ms a 999ms (a |)

希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.