如何使用茉莉花大理石在rxjs管道中测试timeout() [英] How to test timeout() in a rxjs pipe with jasmine-marbles

查看:157
本文介绍了如何使用茉莉花大理石在rxjs管道中测试timeout()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have written a pipe that filters an input observable. In the pipe I specify a timeout with the timeout() operator to abort waiting if the expected value is not emitted by the source in time. I want to test the timeout case with jasmine-marbles, but I can't get it to work. I believe that expect(source).toBeObservable() evaluates before the source emits.

请参见 Stackblitz

要测试的管道:

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

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

Testing with toPromise() works as expected:

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

用茉莉花大理石进行测试

Testing with jasmine-marbles

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

推荐答案

最近添加了对时间进度的支持(

Support for time progression was recently added (see jasmine-marbles PR #38) to jasmine-marbles 0.5.0. Additional test specs were added to the package that demonstrate one of a couple of possible ways to accomplish what you want. Here are some options I was able to throw together using your Stackblitz sample.

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

When you initialize the source observable outside the test method (e.g. in beforeEach), you must explicitly initialize and pass the test scheduler to timeout to get expect().toBeObservable() working. However, take note that this change will break the "should work with toPromise" test. (I don't know why, but toPromise() doesn't appear to work with this approach.)

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

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

Option 2

You can refactor things slightly and initialize the source observable inside the test method (not in beforeEach). You don't need to explicitly initializes the test scheduler (jasmine-marbles will do it for you before the test method runs), but you still have to pass it to timeout. Note how the createSource function can be used with the test scheduler or the default scheduler (if the scheduler argument is left undefined). This options works with both the "should work with toPromise" test and the "should work with toBeObservable" test.

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

选项3

最后,如果您明确使用测试计划程序的run方法,则可以跳过将测试计划程序传递给timeout的步骤,但是必须使用expectObservable(而不是expect().toBeObservable().它可以正常工作,但是茉莉花香将报告警告规格没有预期".

Option 3

Finally, you can skip passing the test scheduler to timeout if you explicitly use the test scheduler's run method, but you must use expectObservable (as opposed to expect().toBeObservable(). It works just fine, but Jasmine will report the warning "SPEC HAS NO EXPECTATIONS".

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

  let source;

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

  it('should work with scheduler and expectObservable', () => {
    const scheduler = getTestScheduler();
    scheduler.run(({ expectObservable }) => {
      expectObservable(source).toBe('500ms (0|)', [{ timeout: true }]);
    });
  });
});

这篇关于如何使用茉莉花大理石在rxjs管道中测试timeout()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆