Jasmine/Angular报filter空引用错误 如何正确mock Location类
错误原因
你遇到的报错核心是两点:
- mock的
getState()返回值不符合组件逻辑预期:组件中是先调用location.getState()拿到完整的路由状态对象,再读取对象上的filter属性,但你当前写的mock类里,getState()直接返回了字符串'Germany',字符串本身不存在filter属性,逻辑完全不匹配。 - 匿名类mock的方式在Angular DI中稳定性差,大概率实际注入的还是原生
Location类,测试环境下原生Location.getState()没有提前写入状态时默认返回null,读取null上的filter属性就会抛出你看到的Cannot read property 'filter' of null错误。
正确mock方案
优先选择useValue直接传入mock实例,不要用匿名类的useClass写法,有两种常用实现:
方案1:固定返回值简单mock
适合不需要校验方法调用、只需要保证逻辑跑通的场景,直接在providers中配置:
import { Location } from '@angular/common'; providers: [ { provide: Location, useValue: { // getState直接返回组件预期的完整状态对象 getState: () => ({ filter: 'Germany' }), // 如果组件中还用到Location的其他方法(比如back、go等),在这里补充对应mock即可 } } ]
方案2:Jasmine Spy mock
适合需要校验方法调用参数、调用次数,或者需要动态修改返回值的场景:
import { Location } from '@angular/common'; let locationSpy: jasmine.SpyObj<Location>; beforeEach(async () => { // 创建包含需要mock方法的spy实例 locationSpy = jasmine.createSpyObj('Location', ['getState']); // 配置getState的默认返回值 locationSpy.getState.and.returnValue({ filter: 'Germany' }); await TestBed.configureTestingModule({ declarations: [SchedulingListComponent], providers: [ { provide: Location, useValue: locationSpy } ] }).compileComponents(); }); // 后续测试用例中可以动态修改返回值,或者断言调用情况 it('test case', () => { locationSpy.getState.and.returnValue({ filter: 'France' }); // 执行组件逻辑后断言 expect(component.schedulingFilter).toBe('France'); });
注意:如果组件中还用到
Location的其他方法,一定要在mock中补充对应实现,否则调用时会报方法不存在的错误。
内容的提问来源于stack exchange,提问作者Jonathan Benevides
相关产品推荐
相关产品推荐

