1

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

在那之后,我编写了一个测试,但我无法让它接近发生的事情。

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

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

我希望大理石图接近-# 5s # 5s (a|)(在测试中还有另一个图,因为我尝试了不同的图)。

4

1 回答 1

1

看起来你颠倒mergeMap()retryWhen(). timer(100)如果尝试少于 3 次,您应该返回,如下所示:

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);
    });
  });
});

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

如果某个内部 observable 发生错误并由内部运算符处理,则从外部看不到它。所以,期望值不能像-# 5s # 5s (a|). 基于弹珠'-#''-#''-a'提供给cold可观察对象,预期输出将是'203ms a'(等待 3 次 1 毫秒 3 个-标志 + 两个timers 等待 100 毫秒两个错误,然后发出a)。

由于源 observable 没有终端事件(最后一个,您打算重新订阅retryWhen),因此您根本无法在预期的弹珠中出现终端事件。如果您需要终端事件,请-a|在第三个coldobservable 和'203ms a|'as中使用它expected

于 2019-08-28T12:25:25.357 回答