RxJs大理石测试重试时间

时间:2019-08-08 06:31:27

标签: testing rxjs jasmine rxjs-marbles

我有一个SocketService。此类负责套接字连接和与服务器的消息传递。我编写了一些代码,以使客户端能够在连接断开时重新连接。它应该进行3次尝试,两次尝试之间要间隔5秒,如果没有成功,则会重定向到登录页面。

在那之后,我编写了一个测试,但是我无法使其工作甚至接近发生的事情。

我正在尝试模拟send上的2个错误和一条成功的消息。什么会导致3次重新连接尝试和最后一次成功的连接。

这是我的考试https://stackblitz.com/edit/jasmine-marbles-testing-jdvcnm?file=src/test.spec.ts

我希望大理石图在-# 5s # 5s (a|)附近(在测试中,由于我尝试了不同的图,所以还有另一张图)。

1 个答案:

答案 0 :(得分:0)

似乎您颠倒了mergeMap()中使用的retryWhen()运算符的逻辑。如果尝试次数少于3次,则应返回timer(100),如下所示:

describe('marble', () => {
  let service: SocketService;

  beforeEach(() => service = new SocketService());

  it('should make 3 attempts and reconnect on 3rd', () => {
    const values = {
      a: {
        status: 200
      }
    };
    const expected = '203ms a';

    (service as any).socket = {};

    spyOn(localStorage, 'getItem').and.returnValue('hello');

    testScheduler.run(({ cold, expectObservable }) => {
      const source$ = createRetryableStream(
        cold('-#'),
        cold('-#'),
        cold('-a', values)
      ).pipe(
        retryWhen(errors => errors.pipe(
          mergeMap((err, i) => {
            return 3 > i
              ? timer(100, testScheduler)
              : throwError(err);
          })
        ))
      );

      // trigger close socket event to make listener work
      service.onClose.next();

      expectObservable(source$).toBe(expected, values);
    });
  });
});

除此之外,期望多个终端事件是不正确的。最多只能有一个终端事件(错误或完成)(这意味着您不必有任何事件)。

如果某个内部可观察到的错误发生并由内部运算符处理,则从外部看不到该错误。因此,期望值不能像-# 5s # 5s (a|)。根据提供给'-#'观测值的大理石'-#''-a'cold,预期输出将为'203ms a'(3 { 1}}符号+两个-,等待100 ms的两个错误,然后发出timer)。

由于可观察的源没有终端事件(最后一个目标是您打算用a重新订阅),因此根本无法在预期的弹珠中发生终端事件。如果您需要结束事件,请在可观察到的第三个retryWhen中使用此-a|,并将cold用作'203ms a|'