使用jasmine-marble为含withLatestFrom的代码编写单元测试报错如何解决
问题修复方案
错误原因拆解
你遇到的报错是由3个核心写法错误导致的:
- 断言对象错误:你直接把
app.getData方法本身传入了toBeObservable,但该方法需要接收Observable实例作为匹配对象,你需要先调用getData()拿到返回的流再断言。 - 预期流结构不符合
withLatestFrom的行为:withLatestFrom组合两个Observable后,只会发射单个数组值,数组内按顺序包含两个源Observable的最新值,而不是分两次发射两个独立的布尔值。你写的(cd|)表示同一时间帧发射两个next通知+1个complete通知,和实际流的输出结构不匹配,也是你看到notification.kind匹配失败的直接原因。 - 未提前触发依赖Observable的发射:
withLatestFrom只会在上游Observable(也就是this.firstObservableClass)发射值时,才组合this.secObservableClass的最新值,如果你没有在测试中提前模拟两个依赖Observable的发射,实际流不会产出你预期的值。
修复后的测试用例写法
首先你需要先模拟两个依赖的Observable,再构造正确的预期流,最后断言:
// 1. 先模拟两个依赖的Observable的发射行为 const first$ = cold('a', { a: true }); const sec$ = cold('b', { b: true }); // 把组件内的两个Observable替换成你模拟的流 app.firstObservableClass = first$; app.secObservableClass = sec$; // 2. 构造正确的预期流:withLatestFrom返回的是单个数组值,之后完成 // 这里的(x|)表示同一时间帧发射一个next值、然后立即完成 const expected = cold('(x|)', { x: [true, true] }); // 3. 调用getData拿到返回的Observable,再做断言 expect(app.getData()).toBeObservable(expected); // 触发冷流的订阅执行 flush();
如果你getData()内部是订阅之后没有把Observable返回出来,那你需要调整组件代码,把pipe之后的Observable作为返回值返回,否则无法直接用toBeObservable断言。
额外注意事项
- 如果你不需要关心流的完成通知,只需要关心发射的值,可以把预期流写成
x,不需要加|,避免匹配不必要的complete事件。 - 要确保两个依赖的Observable在
firstObservableClass发射之前,secObservableClass已经有过发射值,否则withLatestFrom不会触发输出。
内容的提问来源于stack exchange,提问作者user16836526
相关产品推荐
相关产品推荐

