如何修复Jasmine Marble测试ngLogger时的Expected系列错误?
解决Jasmine Marble测试ngLogger函数时的错误问题
我来帮你拆解这些错误的含义,以及对应的修复方案:
先搞懂你遇到的每个错误到底在说什么
Expected $.length = 2 to equal 1
这个错误是说:你测试的Observable实际发出了2个通知(一个next发射值,一个complete结束流),但你写的预期流只定义了1个通知。因为of()创建的Observable会在发射值后自动触发complete,如果你的预期Marble没包含结束标记|,就会出现数量不匹配。Expected $[0].frame = 0 to equal 10
Marble语法里,-代表10个时间帧的延迟。你写的hot('-a')表示要在第10帧发射值,但ngLogger里的of()是同步执行的,会在第0帧就立刻发出值,所以时间节点完全对不上。Expected $[0].notification.value to be a kind of Observable, but was Object(...)
这里的问题最关键:你把expected定义成了of(...)(一个Observable),然后把它作为hot('-a')里的a值,导致预期流发射的是Observable对象。但ngLogger返回的流发射的是Log类型的普通对象,两者的value类型完全不匹配,自然报错。
修复后的测试代码
核心思路是让预期流和实际流的发射内容、时间、生命周期完全对齐:
import { cold, expectObservable } from 'jasmine-marbles'; import { GlobalUtils } from './global.utils'; it('ngLogger should return an Observable emitting the correct Log object', () => { // 1. 定义预期的Log对象,和ngLogger返回的内容完全一致 const expectedLog = { type: LogEnum.TECHNICAL, level: LevelEnum.ERROR, msg: 'test' } as Log; // 2. 用cold定义预期流:0帧发射值,立即完成(|表示complete) const expected$ = cold('a|', { a: expectedLog }); const result$ = GlobalUtils.ngLogger('test'); // 3. 断言实际流和预期流一致 expectObservable(result$).toBeObservable(expected$); });
或者更简化的写法(因为同步流可以直接用Marble字符串断言):
it('ngLogger should return an Observable emitting the correct Log object', () => { const expectedLog = { type: LogEnum.TECHNICAL, level: LevelEnum.ERROR, msg: 'test' } as Log; // (a|) 表示在同一帧内完成发射和结束 expectObservable(GlobalUtils.ngLogger('test')).toBe('(a|)', { a: expectedLog }); });
修复的核心要点总结
- 不要把Observable作为预期的发射值:
ngLogger返回的流是发射Log对象,所以预期的value必须是Log对象本身,而非包裹它的Observable。 - 匹配同步流的时间:
of()是同步发射,对应Marble里的0帧,用a|或(a|)表示立即发射并完成。 - 对齐流的生命周期:
of()创建的流会自动结束,所以预期Marble必须包含|,否则会出现通知数量不匹配的错误。
内容的提问来源于stack exchange,提问作者Ursule Maffo
相关产品推荐
相关产品推荐

