Angular 4单元测试报错:undefined is not a constructor(subscribe调用时)
TypeError: undefined is not a constructor (evaluating 'this.service.getDat().subscribe')的问题 我来帮你拆解这个报错的原因和解决办法,你遇到的这个问题其实是单元测试里Mock服务配置的两个常见错误导致的:
核心报错原因
Mock服务的方法名与真实服务不匹配
你的组件代码里调用的是this.service.getData(),但你写的Mock服务类MockUserRolesService里定义的方法是getModulesData()——这就导致组件调用getData()时,这个方法根本不存在,返回undefined,自然无法调用subscribe()方法。Mock方法返回的不是Observable类型
真实的LayoutService的getData()方法应该是返回一个Observable(因为你在组件里调用了subscribe()),但你的Mock方法直接返回了普通对象modulesData,普通对象没有subscribe方法,这也会触发类似的报错。
解决步骤
步骤1:修正Mock服务的方法名和返回值
把Mock服务的方法名改成和真实服务一致的getData(),并且用RxJS的of()操作符把模拟数据包装成Observable:
import { of } from 'rxjs'; // 修正后的Mock服务 class MockUserRolesService { public getData() { // 模拟真实接口返回的结构,确保组件能正常解析 return of({ _body: JSON.stringify({ 'moduleName':'Info' }) }); } }
注意:因为你的组件里对返回的
res做了JSON.parse(res._body),所以Mock返回的数据要和真实接口的结构匹配,这里我把模拟数据包装成了带有_body属性的对象,再转成JSON字符串,确保组件逻辑能正常执行。
步骤2:确保测试模块中正确替换服务
在beforeEach的TestBed.configureTestingModule配置里,把真实的LayoutService替换成你的Mock服务:
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [YourComponent], // 替换成你的实际组件类名 providers: [ { provide: LayoutService, useClass: MockUserRolesService } ] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(YourComponent); component = fixture.componentInstance; // 获取注入的Mock服务实例(可选,如果你需要在测试中验证调用) userRolesService = TestBed.inject(LayoutService); fixture.detectChanges(); });
步骤3:验证测试逻辑
现在运行单元测试,组件在ngOnInit里调用this.service.getData()时,会调用Mock服务的getData()方法,返回一个Observable,就能正常调用subscribe()了,不会再触发报错。
额外提示
如果你需要测试错误分支(比如接口请求失败的情况),可以用throwError()来返回一个错误Observable:
import { throwError } from 'rxjs'; // 模拟请求失败的Mock方法 public getData() { return throwError(() => new Error('请求失败')); }
内容的提问来源于stack exchange,提问作者Siva

