3 回答

TA贡献1829条经验 获得超13个赞
RxJS v6
对于RxJS v6代码,如下所示:
code.js
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
export const example = of('hello').pipe(
delay(1000)
);
...您可以使用sinon 伪造的计时器,如下所示:
import * as sinon from 'sinon';
import { example } from './code';
describe('delay', () => {
let clock;
beforeEach(() => { clock = sinon.useFakeTimers(); });
afterEach(() => { clock.restore(); });
it('should delay one second', () => {
const spy = jest.fn();
example.subscribe(spy);
expect(spy).not.toHaveBeenCalled(); // Success!
clock.tick(1000);
expect(spy).toHaveBeenCalledWith('hello'); // Success!
});
});
(请注意,在编写Jest 计时器模拟时不起作用,不确定原因)
...或者您可以嘲笑delay不执行以下操作:
import { delay } from 'rxjs/operators';
import { example } from './code';
jest.mock('rxjs/operators', () => {
const operators = jest.requireActual('rxjs/operators');
operators.delay = jest.fn(() => (s) => s); // <= mock delay
return operators;
});
describe('delay', () => {
it('should delay one second', () => {
const spy = jest.fn();
example.subscribe(spy);
expect(delay).toHaveBeenCalledWith(1000); // Success!
expect(spy).toHaveBeenCalledWith('hello'); // Success!
});
});
RxJS v5
对于RxJS v5这样的代码:
code.js
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';
export const example = Observable.of('hello').delay(1000);
...您可以嘲笑delay不执行以下操作:
import { Observable } from 'rxjs/Observable';
import { example } from './code';
jest.mock('rxjs/add/operator/delay', () => {
const Observable = require('rxjs/Observable').Observable;
Observable.prototype.delay = jest.fn(function () { return this; }); // <= mock delay
});
describe('delay', () => {
it('should delay one second', () => {
const spy = jest.fn();
example.subscribe(spy);
expect(Observable.prototype.delay).toHaveBeenCalledWith(1000); // Success!
expect(spy).toHaveBeenCalledWith('hello'); // Success!
});
});

TA贡献1807条经验 获得超9个赞
我们正在使用SchedulerRxjs中的。
类看起来像这样:
import { Observable, Scheduler, Subject, asapScheduler } from 'rxjs';
// ...
constructor(
@Optional() private readonly _scheduler: Scheduler
) {
if (isNullOrUndefined(_scheduler)) {
this._scheduler = asapScheduler;
}
}
// ...
this._someObservable.pipe(delay(1, this._scheduler));
然后,在spec文件中提供一个模拟TestModuleMetadata:
{
declarations: [YourComponent],
imports: [],
providers: [
{ provide: Scheduler, useValue: new VirtualTimeScheduler() },
],
};
现在,您需要做的就是在一个beforeEach块中分配调度程序,并在您希望延迟被“跳过”时刷新它:
let schedulerMock = Testbed.get(Scheduler);
// ...
it('should emit true', () => {
let result: boolean = null;
comp.someObservable.subscribe(next => (result = next));
schedulerMock.flush();
expect(result).toBe(true);
});
这也适用于其他时间依赖运算符,例如bufferTime。您要使用或需要在组件中使用哪个调度程序应取决于您的用例,在最佳情况下,请查阅文档并找出最适合您的方案。

TA贡献1874条经验 获得超12个赞
从版本6.2.1开始,RxJS支持Jest的假时间,因此您可以简单地编写
jest.useFakeTimers('modern');
test('...', () => {
// ...code that subscribes to your observable.
jest.runAllTimers();
// ...code that makes assertions.
});
另外,我已经发布了一个库,使编写这样的测试变得更加容易,这是一个示例(log将日志记录添加到可观察对象中,getMessages检索日志记录的消息):
import { getMessages, log } from '1log';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
test('delay', () => {
of(42).pipe(delay(500), log).subscribe();
jest.runAllTimers();
expect(getMessages()).toMatchInlineSnapshot(`
[create 1] +0ms [Observable]
[create 1] [subscribe 1] +0ms [Subscriber]
[create 1] [subscribe 1] [next] +500ms 42
[create 1] [subscribe 1] [complete] +0ms
· [create 1] [subscribe 1] [unsubscribe] +0ms
`);
});
添加回答
举报