如何合并RxJS marble图表 测试多帧发射的Observable
问题根因
- 你自行拼接的marble不符合预期,是因为对marble语法的帧计算规则理解有误:
()包裹的所有值属于同一帧,括号本身的字符长度不会占用额外帧位,你之前认为(bcdef)占5帧所以g跑到第9帧,是错误的认知。 - 你使用
combineLatest报错,是因为该操作符的特性不符合需求:它需要所有输入Observable都至少发射过一次值才会输出,且输出的是所有输入最新值的数组,无法还原你预期的依次独立发射a~g的逻辑。
可行方案
有两种实现方式都可以满足测试需求:
方案1:直接编写正确的单个marble图
按照marble语法规则,你要的发射逻辑对应的单marble写法如下:
'-a(bcdef)g'
对应的帧发射逻辑完全符合你的要求:
- 帧0:无发射
- 帧1:发射
a - 帧2:同步发射
b/c/d/e/f - 帧3:发射
g
对应的测试代码示例:
const values = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }; expectObservable(你的被测Observable$).toBe('-a(bcdef)g', values);
如果你之前测试时发现g跑到第9帧,大概率是你的测试代码存在其他错误(比如传入的marble多写了额外的横杠、值映射错误等),可以核对下marble字符串的写法。
方案2:合并多个marble Observable
如果你确实需要拆分多个marble来写,不要用combineLatest,改用merge操作符即可,它会按时间线合并多个Observable的发射,不改变每个值的原始发射时间,完全符合你的需求:
import { merge } from 'rxjs'; import { cold } from 'jasmine-marbles'; // 或你使用的测试库对应的cold方法 const values = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }; const expected1$ = cold('-a(bcdef)', values); const expected2$ = cold('--g', values); const expected$ = merge(expected1$, expected2$); expectObservable(你的被测Observable$).toBe(expected$);
内容的提问来源于stack exchange,提问作者Valentine
相关产品推荐
相关产品推荐

