如何使用茉莉花大理石在rxjs管道中测试timeout()

时间:2019-04-23 21:02:49

标签: unit-testing rxjs timeout jasmine-marbles

我编写了一个过滤可观察输入的管道。在管道中,我使用timeout()运算符指定一个超时,以在源未及时发出期望值的情况下中止等待。 我想用茉莉花大理石测试超时情况,但无法正常工作。 我相信 expect(source).toBeObservable()在源发出之前进行评估。

请参阅Stackblitz

要测试的管道:

source = cold('a', { a: { id: 'a' } }).pipe(
  timeout(500),
  filter((a) => false),
  catchError((err) => {
    return of({ timeout: true })
  }),
  take(1)
);

使用toPromise()进行测试按预期进行:

expect(await source.toPromise()).toEqual({ timeout: true });

用茉莉花大理石进行测试

const expected = cold('500ms (a|)', { a: { timeout: true } });
expect(source).toBeObservable(expected);

失败,并显示错误

Expected $.length = 0 to equal 2.
Expected $[0] = undefined to equal Object({ frame: 500, notification: Notification({ kind: 'N', value: Object({ timeout: true }), error: undefined, hasValue: true }) }).
Expected $[1] = undefined to equal Object({ frame: 500, notification: Notification({ kind: 'C', value: undefined, error: undefined, hasValue: false }) }).

1 个答案:

答案 0 :(得分:1)

最近为茉莉花大理石0.5.0添加了对时间进展的支持(see jasmine-marbles PR #38)。软件包中添加了其他测试规范,这些规范说明了完成所需目标的两种可能方法之一。这是一些我可以使用Stackblitz示例将其组合在一起的选项。

选项1

在测试方法之外(例如,在beforeEach中初始化可观察的源时,必须显式初始化并将测试调度程序传递给timeout,以使expect().toBeObservable()正常工作。但是,请注意,此更改将破坏“应该与toPromise一起使用”测试。 (我不知道为什么,但是toPromise()似乎不适用于这种方法。)

describe('Marble testing with timeout', () => {

  let source;

  beforeEach(() => {
    // You must explicitly init the test scheduler in `beforeEach`.
    initTestScheduler()
    source = cold('a', { a: { id: 'a' } }).pipe(
      // You must explicitly pass the test scheduler.
      timeout(500, getTestScheduler()),
      filter((a) => false),
      catchError(err => {
        return of({ timeout: true })
      }),
      take(1)
    );
  });

  it('should work with toBeObservable', () => {
    const expected = cold('500ms (a|)', { a: { timeout: true } });
    expect(source).toBeObservable(expected);
  });
});

选项2

您可以稍作重构,并初始化测试方法({{1}中的 not )中可观察到的源。您无需显式初始化测试调度程序(茉莉花色大理石将在测试方法运行之前为您完成),但是您仍然必须将其传递给beforeEach。请注意如何将timeout函数与测试调度程序或默认调度程序一起使用(如果将createSource参数保留为scheduler)。此选项适用于“应与toPromise一起使用”测试和“应与toBeObservable”一起使用。

undefined

选项3

最后,如果您明确使用测试计划程序的describe('Marble testing with timeout', () => { const createSource = (scheduler = undefined) => { return cold('a', { a: { id: 'a' } }).pipe( // You must explicitly pass the test scheduler (or undefined to use the default scheduler). timeout(500, scheduler), filter((a) => false), catchError(err => { return of({ timeout: true }) }), take(1) ); }; it('should work with toPromise', async () => { const source = createSource(); expect(await source.toPromise()).toEqual({ timeout: true }); }); it('should work with toBeObservable', () => { const source = createSource(getTestScheduler()); const expected = cold('500ms (a|)', { a: { timeout: true } }); expect(source).toBeObservable(expected); }); }); 方法,则可以跳过将测试计划程序传递给timeout的步骤,但是必须使用run(而不是expectObservable 。它可以正常工作,但是Jasmine将报告警告“ SPEC HA EXPECTATIONS”。

expect().toBeObservable()