如何使用 jasmine-marbles 在 rxjs 管道中测试 timeout()
How to test timeout() in a rxjs pipe with jasmine-marbles
我写了一个过滤输入可观察对象的管道。在管道中,我使用 timeout() 运算符指定一个超时,以在源未及时发出预期值时中止等待。
我想用 jasmine-marbles 测试超时情况,但我无法让它工作。
我 相信 expect(source).toBeObservable()
在源发出之前进行评估。
待测管道:
source = cold('a', { a: { id: 'a' } }).pipe(
timeout(500),
filter((a) => false),
catchError((err) => {
return of({ timeout: true })
}),
take(1)
);
使用 toPromise() 进行测试按预期工作:
expect(await source.toPromise()).toEqual({ timeout: true });
用 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 }) }).
最近向 jasmine-marbles 0.5.0 添加了对时间进展的支持 (see jasmine-marbles PR #38)。额外的测试规范被添加到包中,演示了实现您想要的目标的几种可能方法之一。以下是我使用您的 Stackblitz 示例拼凑出的一些选项。
选项 1
当您在测试方法之外初始化源可观察对象时(例如在 beforeEach
中),您必须显式初始化并将测试调度程序传递给 timeout
以使 expect().toBeObservable()
工作。但是,请注意此更改将破坏 "should work with toPromise" 测试。 (我不知道为什么,但 toPromise()
似乎不适用于这种方法。)
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
您可以稍微重构并在测试方法中初始化可观察源(不是 in beforeEach
)。您不需要显式初始化测试调度程序(jasmine-marbles 会在测试方法运行之前为您完成),但您仍然必须将其传递给 timeout
。请注意 createSource
函数如何与测试调度程序或默认调度程序一起使用(如果 scheduler
参数保留为 undefined
)。此选项适用于 "should work with toPromise" 测试和 "should work with toBeObservable" 测试。
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
(与 [=15 相反) =]. 运行正常,但是Jasmine会报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 }]);
});
});
});
我写了一个过滤输入可观察对象的管道。在管道中,我使用 timeout() 运算符指定一个超时,以在源未及时发出预期值时中止等待。
我想用 jasmine-marbles 测试超时情况,但我无法让它工作。
我 相信 expect(source).toBeObservable()
在源发出之前进行评估。
待测管道:
source = cold('a', { a: { id: 'a' } }).pipe(
timeout(500),
filter((a) => false),
catchError((err) => {
return of({ timeout: true })
}),
take(1)
);
使用 toPromise() 进行测试按预期工作:
expect(await source.toPromise()).toEqual({ timeout: true });
用 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 }) }).
最近向 jasmine-marbles 0.5.0 添加了对时间进展的支持 (see jasmine-marbles PR #38)。额外的测试规范被添加到包中,演示了实现您想要的目标的几种可能方法之一。以下是我使用您的 Stackblitz 示例拼凑出的一些选项。
选项 1
当您在测试方法之外初始化源可观察对象时(例如在 beforeEach
中),您必须显式初始化并将测试调度程序传递给 timeout
以使 expect().toBeObservable()
工作。但是,请注意此更改将破坏 "should work with toPromise" 测试。 (我不知道为什么,但 toPromise()
似乎不适用于这种方法。)
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
您可以稍微重构并在测试方法中初始化可观察源(不是 in beforeEach
)。您不需要显式初始化测试调度程序(jasmine-marbles 会在测试方法运行之前为您完成),但您仍然必须将其传递给 timeout
。请注意 createSource
函数如何与测试调度程序或默认调度程序一起使用(如果 scheduler
参数保留为 undefined
)。此选项适用于 "should work with toPromise" 测试和 "should work with toBeObservable" 测试。
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
(与 [=15 相反) =]. 运行正常,但是Jasmine会报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 }]);
});
});
});