Angular Jasmine测试中mock ActivatedRoute链式方法触发get未定义报错
错误原因
ActivatedRoute实例的snapshot是属性而非方法,snapshot下的paramMap也是属性而非方法,你将两者写在jasmine.createSpyObj的方法列表里,会导致访问activatedRoute.snapshot得到的是未执行的spy函数,而非预期的对象,链式访问paramMap自然为undefined,调用get方法就抛出了该错误。- 额外错误:
snapshot.paramMap.get是同步方法,不需要返回of("testId")这类Observable值,你写的返回值也不符合实际API定义。
解决方案
最简mock写法(适合大多数场景)
直接构造符合嵌套结构的对象即可,只给需要调用的get方法做spy:
activatedRoute = { snapshot: { paramMap: { get: jasmine.createSpy('get').and.returnValue('testId') } } } as ActivatedRoute;
全spy写法(需要监控属性访问时使用)
如果需要对snapshot、paramMap的访问做监控,使用jasmine.createSpyObj的第三个参数定义属性:
// 构造paramMap spy,仅包含get方法 const paramMapSpy = jasmine.createSpyObj('ParamMap', ['get']); paramMapSpy.get.and.returnValue('testId'); // 构造snapshot spy,paramMap是其属性 const snapshotSpy = jasmine.createSpyObj('ActivatedRouteSnapshot', [], { paramMap: paramMapSpy }); // 构造ActivatedRoute spy,snapshot是其属性 activatedRoute = jasmine.createSpyObj('ActivatedRoute', [], { snapshot: snapshotSpy });
如果你的业务代码后续会用到非snapshot的响应式paramMap(即this.route.paramMap.pipe(...)的写法),可以在ActivatedRoute的属性中额外添加对应mock:
activatedRoute = { snapshot: { paramMap: { get: () => 'testId' } }, paramMap: of({ get: () => 'testId' }) } as ActivatedRoute;
内容的提问来源于stack exchange,提问作者Rattus
相关产品推荐
相关产品推荐

