Angular中如何用jasmine-marbles测试observable响应修改的变量值
测试解决方案
你测试报错的核心原因是jasmine-marbles的流比对匹配器仅支持Observable类型的比对目标,而你要校验的even是普通布尔变量,二者类型不匹配导致测试失败。以下是两种可直接落地的实现方案:
方案1:使用jasmine-marbles测试
无需修改业务代码,通过监听even的赋值动作把变更转换为流之后再做比对:
import { Subject } from 'rxjs'; import { cold, expectObservable } from 'jasmine-marbles'; it('should update even property along with obs emission', () => { // 构造mock的响应流 const responses$ = cold('a-b-c-', { a: 3, b: 4, c: 5 }); // 替换myService的obs属性为mock流,根据你实际的service注入方式调整即可 component.myService.obs = responses$; // 用Subject记录even的每次变更 const evenChange$ = new Subject<boolean>(); // 监听even的赋值动作 spyOnProperty(component, 'even', 'set').and.callFake((val: boolean) => { // @ts-ignore 存储实际值到组件私有属性,保证组件内部逻辑正常运行 component._even = val; evenChange$.next(val); }); spyOnProperty(component, 'even', 'get').and.callFake(() => { // @ts-ignore 读取存储的实际值 return component._even; }); // 触发ngOnInit执行订阅 component.ngOnInit(); // 构造预期流,时间线和响应流对齐即可 const expected$ = cold('a-b-c-', { a: false, b: true, c: false }); expectObservable(evenChange$).toEqual(expected$); });
方案2:使用Angular自带的fakeAsync工具测试
不需要依赖jasmine-marbles的流比对能力,直接逐帧推进时间校验变量值,写法更直观:
import { fakeAsync, tick } from '@angular/core/testing'; import { cold } from 'jasmine-marbles'; it('should update even property correctly', fakeAsync(() => { const responses$ = cold('a-b-c-', { a: 3, b: 4, c: 5 }); component.myService.obs = responses$; component.ngOnInit(); // marbles语法每个字符默认代表10ms时间间隔 tick(0); // 推进到第一帧,响应a=3发出 expect(component.even).toBeFalse(); tick(10); // 推进到第二帧,响应b=4发出 expect(component.even).toBeTrue(); tick(10); // 推进到第三帧,响应c=5发出 expect(component.even).toBeFalse(); }));
注:如果你的项目没有引入jasmine-marbles,也可以直接用
of(3,4,5)配合delay操作符模拟不同时间的发射值,逻辑完全一致。
内容的提问来源于stack exchange,提问作者super IT guy
相关产品推荐
相关产品推荐

