如何在 rxjs 5 中使用定时间隔测试 returns 可观察值的函数?

How do I test a function that returns an observable using timed intervals in rxjs 5?

比如我有这样一个函数:

export function timeRange(start: number, end: number): Rx.Observable<number> {
  return Rx.Observable.interval(1000)
  .map(n => n + start)
  .take(end - start + 1)
}

我有一个单元测试 运行 timeRange(10, 100) 并针对它断言值。

问题是时间间隔会使我的测试过长 运行。

如何在不触及函数本身的情况下缩短时间间隔?

我尝试阅读有关调度程序的文档,但我没有理解。

您创建 TestSchedulerVirtualTimeScheduler 并将其作为可选的第二个参数传递给 Observable.Interval。在您的情况下,您只需向 timeRange 添加一个可选的调度程序参数并将值传递给

这些测试调度程序允许您 "pass time" 无需等待实际时间过去。

有关更多信息和示例,请参阅 Testing your Rx Application

我最近遇到了同样的问题并发现 marble testing 它可以让你编写很棒的可视化测试,使定时 Observable 测试变得非常容易。

Marble 测试抽象化了时间并立即测试 运行(通过在引擎盖下使用 TestScheduler),但您仍然可以测试复杂的定时过程。这是一个示例测试,可让您了解语法:

it('should set up an interval', () => {
  const expected = '----------0---------1---------2---------3---------4---------5---------6-----';
  expectObservable(Observable.interval(100, rxTestScheduler)).toBe(expected, [0, 1, 2, 3, 4, 5, 6]);
});

这实际上是来自 rxjs5 存储库的 Observable.interval 的官方单元测试:https://github.com/ReactiveX/rxjs/blob/master/spec/observables/interval-spec.ts

查看 official documentation 了解更多信息。

获取它 运行ning 有点挑战,但您基本上需要的是 marble testing example project 中的两个文件 marble-testing.tstest-helper.ts

有一些注意事项,但您可以按如下方式测试您的功能:

const Rx = require('rxjs');
const chai = require('chai');

function timeRange(start, end, interval = 1000, scheduler = Rx.Scheduler.async) {
  return Rx.Observable.interval(interval, scheduler)
    .map(n => n + start)
    .take(end - start + 1)
}

let scheduler = new Rx.TestScheduler(chai.assert.deepEqual);
let source = timeRange(2, 8, 50, scheduler);
let values = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8};
scheduler.expectObservable(source).toBe('-----2----3----4----5----6----7----(8|)', values);

scheduler.flush();

注意几点:

  • 函数现在有四个参数。我们需要用来传递TestScheduler.

  • 的区间和Scheduler
  • TestScheduler 需要获取一种方法来深入比较对象。它将用于比较 Notification 个对象的数组。

  • 您不能使用 1000,因为允许的最长时间为 hardcoded as 750。请注意,这只是虚拟时间,与实时无关,因此我们在此测试中使用的 5050ms 不同。我们只需要适应 750 时间范围。

  • 然后像典型的弹珠测试一样进行弹珠测试。有关详细信息,请参阅 https://github.com/ReactiveX/rxjs/blob/master/doc/writing-marble-tests.md。请注意,我不能使用与默认 RxJS 运算符相同的全局 mocha 函数。

  • 我还必须指定值,因为大理石测试默认使用字符串,我需要强制使用整数以确保深度相等。

您可以通过更改一个大理石值来测试此操作是否失败:

let values = {'2': 42, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8};

此外,您可以通过将它们打印到控制台来查看通知对象是什么:

let scheduler = new TestScheduler((actual, expected) => {
   console.log('Actual:', actual, '\n\n', 'Expected:', expected);
   chai.assert.deepEqual(actual, expected);
});

使用 RxJS 5 mocha 助手

此时 RxJS 5 不公开 mocha 测试助手。我实际上在我现在正在处理的另一个项目中使用它(包括生成图表图像)。您可以在这里查看 https://github.com/martinsik/rxjs-extra into package.json what scripts I'm using. It works well but the setup is a little hard to understand. It involves downloading the RxJS 5 archive, copying a few files and patching it with a couple of files. Then the default options for mocha test are set with mocha.opts,它基于 RxJS 5.

的原始版本

这对我很有效:rxjs-testscheduler-compat。来自自述文件:

rxjs-testscheduler-compat provides RxJS v4's test scheduler interface to v5 version of RxJS allows to migrate existing test cases with minimum effort as well as writing new test cases for certain cases.