测试rxjs的正确方法

时间:2017-01-21 13:24:30

标签: javascript rxjs rxjs5

我带了这本书rxjs in action,刚刚完成测试部分。

测试rxjs代码与通常的测试不同,因为一切都是延迟加载。

在书中,他们提到了两种测试方法,即传递完成(我使用的是QUnit,完成信号,异步代码完成)或大理石图。

我的问题是,我应该选择哪种方法,我上面提到过?

2 个答案:

答案 0 :(得分:9)

我从同事那里得到了很多这个问题。我终于开始记录my ways of testing RxJs on my blog了。由于你的问题似乎与RxJs5有关,我只会在这里引用我的帖子的相关部分。

在RxJs5中以RxJs4方式测试

当您将代码库从RxJs4迁移到5时,您会发现很多东西已被移动,重命名,最重要的是,TestScheduler的实现不再可用。 RxJs贡献者kwonoj创建了一个compatibility shim to help migration towards RxJs5。您可以使用npm npm install @kwonoj/rxjs-testscheduler-compat安装它。并非TestScheduler的所有功能都已实现,但最重要的.startScheduler正在运行。

const TestScheduler = require('@kwonoj/rxjs-testscheduler-compat').TestScheduler;
const next = require('@kwonoj/rxjs-testscheduler-compat').next;
const complete = require('@kwonoj/rxjs-testscheduler-compat').complete;

it('works in RxJs5 with the compat package', () => {
  const scheduler = new TestScheduler(); // Note; no longer the Rx.TestScheduler

  const results = scheduler.startScheduler(
    () => Rx.Observable.interval(100, scheduler).take(3),
    { created: 100, subscribed: 200, unsubscribed: 1000 } // NOTE: disposed is now renamed to unsubscribed
  );

  collectionAssert.assertEqual(res.messages, [
    next(200 + 100, 0),
    next(200 + 200, 1),
    next(200 + 300, 2),
    complete(200 + 300)
  ]);
});

使用新的Marble测试语法

在RxJs5中进行测试

RxJs团队引入了marble testing syntax,以更直观地定义您的运营商或自定义代码应如何运作。

var e1 = hot('----a--^--b-------c--|');
var e2 = hot(  '---d-^--e---------f-----|');
var expected =      '---(be)----c-f-----|';

expectObservable(e1.merge(e2)).toBe(expected);

在撰写本文时,他们还没有使这种方法在RxJs5库本身之外使用起来非常容易。有implementations available看看如何自己做。您还可以在codebase of RxJs5中查看,了解如何设置测试框架以进行自己的大理石测试。有一个开放的issue about documenting testing with RxJs5。我还没有成功地将我的测试框架设置为以这种方式进行大理石测试。

答案 1 :(得分:1)

时间已经过去,现在绝对有可能(甚至很容易)自己使用TestScheduler使用这些大理石测试。它们是一种以易于理解的格式全面测试随时间推移,错误,完成和订阅而产生的排放的好方法。以下是their docs的示例:

import { TestScheduler } from 'rxjs/testing';

const testScheduler = new TestScheduler((actual, expected) => {
  // asserting the two objects are equal
  // e.g. using chai.
  expect(actual).deep.equal(expected);
});

// This test will actually run *synchronously*
it('generate the stream correctly', () => {
  testScheduler.run(helpers => {
    const { cold, expectObservable, expectSubscriptions } = helpers;
    const e1 =  cold('-a--b--c---|');
    const subs =     '^----------!';
    const expected = '-a-----c---|';

    expectObservable(e1.pipe(throttleTime(3, testScheduler))).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });
});

如果您使用茉莉花,我写了一个名为marbleTest()的小助手来减少样板,s-ng-dev-utils中提供了该

import { marbleTest } from "s-ng-dev-utils";

it("generate the stream correctly", marbleTest(helpers => {
  const { cold, expectObservable, expectSubscriptions, testScheduler } = helpers;
  const e1 = cold(" -a--b--c---|");
  const subs = "    ^----------!";
  const expected = "-a-----c---|";

  expectObservable(e1.pipe(throttleTime(3, testScheduler))).toBe(expected);
  expectSubscriptions(e1.subscriptions).toBe(subs);
}));