测试rxjs的正确方法
The right way to test rxjs
我带了书"rxjs in action"刚刚完成了测试部分
测试 rxjs 代码与通常的测试不同,因为一切都是延迟加载。
在书中,他们提到了两种测试方法,通过完成(我正在使用 QUnit 并且完成信号异步代码已完成)或大理石图。
我的问题是,我应该选择上面提到的哪种方法?
我的同事经常问我这个问题。我终于抽出时间来记录 my ways of testing RxJs on my blog。由于您的问题似乎与 RxJs5 有关,因此我只会在此处引用我 post 的相关部分。
在 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);
在撰写本文时 post 他们还没有使这种方法在 RxJs5 库本身之外真正易于使用。有implementations available to see how to do it yourself. You can also look around in the codebase of RxJs5 to see how to setup your testing framework to do your own marble tests. There is an open issue about documenting testing with RxJs5。我还没有成功地设置我的测试框架来以这种方式进行大理石测试。
时间过去了,现在绝对有可能(甚至很容易)使用 TestScheduler
自己使用这些弹珠测试。它们是一种以 easy-to-understand 格式全面测试随时间推移的排放、错误、完成和订阅的好方法。这是来自 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);
});
});
如果你用Jasmine,我写a little helper called marbleTest()
to reduce boilerplate, available in @s-libs/ng-dev
:
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);
}));
我带了书"rxjs in action"刚刚完成了测试部分
测试 rxjs 代码与通常的测试不同,因为一切都是延迟加载。
在书中,他们提到了两种测试方法,通过完成(我正在使用 QUnit 并且完成信号异步代码已完成)或大理石图。
我的问题是,我应该选择上面提到的哪种方法?
我的同事经常问我这个问题。我终于抽出时间来记录 my ways of testing RxJs on my blog。由于您的问题似乎与 RxJs5 有关,因此我只会在此处引用我 post 的相关部分。
在 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);
在撰写本文时 post 他们还没有使这种方法在 RxJs5 库本身之外真正易于使用。有implementations available to see how to do it yourself. You can also look around in the codebase of RxJs5 to see how to setup your testing framework to do your own marble tests. There is an open issue about documenting testing with RxJs5。我还没有成功地设置我的测试框架来以这种方式进行大理石测试。
时间过去了,现在绝对有可能(甚至很容易)使用 TestScheduler
自己使用这些弹珠测试。它们是一种以 easy-to-understand 格式全面测试随时间推移的排放、错误、完成和订阅的好方法。这是来自 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);
});
});
如果你用Jasmine,我写a little helper called marbleTest()
to reduce boilerplate, available in @s-libs/ng-dev
:
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);
}));