Angular2服务单元测试报错:TypeError: service.getValue is not a function
问题根源分析
你遇到的TypeError: service.getValue is not a function错误,核心原因是测试配置里完全替换了MyService的实例:
在TestBed.configureTestingModule的providers中,你用useValue提供了一个自定义对象{ data: Observable.of(dataStub) },这个对象只包含data属性,根本没有MyService类里定义的getValue()方法。所以当测试代码调用service.getValue()时,自然会报错。从你console.log(service)的输出也能看出来,当前的service是那个自定义的Observable对象,不是真正的MyService实例。
解决方案
根据你的测试需求,分三种场景处理:
场景1:不需要mock服务依赖
如果你的测试不需要模拟MyService构造函数里的myOtherObservableReturning依赖(比如只是想测试getValue()方法),直接在providers中声明MyService即可,TestBed会自动创建服务的实例:
beforeEach(() => { TestBed.configureTestingModule({ providers: [MyService] // 直接提供服务类 }); service = TestBed.inject(MyService); // Angular 9+推荐使用inject代替get });
场景2:需要mock服务的依赖
如果MyService构造函数里的myOtherObservableReturning是另一个服务的方法(比如OtherService),你需要先mock这个依赖,避免实际的订阅逻辑影响测试:
// 先定义mock依赖服务 class MockOtherService { // 模拟返回一个空的Observable,避免原服务构造函数里的forEach报错 myOtherObservableReturning = of({ items: [] }); } beforeEach(() => { TestBed.configureTestingModule({ providers: [ MyService, { provide: OtherService, useClass: MockOtherService } // 替换原依赖为mock类 ] }); service = TestBed.inject(MyService); });
场景3:需要部分mockMyService方法
如果只想保留getValue()方法,mock其他逻辑,可以通过继承原服务类来实现:
class MockMyService extends MyService { // 重写需要mock的方法,比如构造函数里的逻辑 constructor() { super(new MockOtherService()); // 传入mock的依赖 } } beforeEach(() => { TestBed.configureTestingModule({ providers: [{ provide: MyService, useClass: MockMyService }] }); service = TestBed.inject(MyService); });
这样修改后,service就会是包含getValue()方法的实例,测试就能正常执行了。
内容的提问来源于stack exchange,提问作者Zainu
相关产品推荐
相关产品推荐

