请求解决Jasmine中spyOn无法找到get()对象的测试错误
解决Angular测试中
spyOn报错:could not find an object to spy upon for get() 错误原因
你触发的错误是因为TestBed.inject(ApiService)获取到的不是Jasmine可识别的间谍对象(SpyObj),直接调用spyOn时,Jasmine找不到可以挂载间谍的目标方法。
解决方案
方法1:在TestBed配置阶段预创建SpyObj(推荐)
在测试初始化阶段就把ApiService替换成SpyObj,这样后续注入的就是可被监听的间谍对象:
describe('blah blah blah', () => { let apiService: jasmine.SpyObj<ApiService>; let component: YourComponent; // 替换成你的组件类名 let fixture: ComponentFixture<YourComponent>; beforeEach(() => { // 创建包含需要监听方法的SpyObj const apiSpy = jasmine.createSpyObj('ApiService', ['get', 'delete']); // 根据实际方法调整 TestBed.configureTestingModule({ declarations: [YourComponent], providers: [ { provide: ApiService, useValue: apiSpy } // 用SpyObj替代真实服务 ] }); // 注入SpyObj apiService = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>; fixture = TestBed.createComponent(YourComponent); component = fixture.componentInstance; fixture.detectChanges(); }); fit('click confirm delete should delete the asset', fakeAsync(() => { // 直接给SpyObj的方法设置返回值 apiService.get.and.returnValue(of({entity: ASSET} as unknown as HttpResponse<null>)); component.reload(); fixture.detectChanges(); // ... 此处添加点击删除按钮的触发逻辑(比如fixture.debugElement.query(By.css('.delete-btn')).triggerEventHandler('click', null);) expect(component.asset).toBeFalsy(); expect(apiService.get).toHaveBeenCalled(); })); });
方法2:测试用例内动态替换为SpyObj(适合特殊场景)
如果需要在单个测试用例中临时替换服务实例,可直接创建SpyObj并赋值给组件的服务引用:
describe('blah blah blah', () => { let apiService: jasmine.SpyObj<ApiService>; let component: YourComponent; let fixture: ComponentFixture<YourComponent>; beforeEach(() => { TestBed.configureTestingModule({ declarations: [YourComponent], providers: [ApiService] // 先注入真实服务,后续替换 }); fixture = TestBed.createComponent(YourComponent); component = fixture.componentInstance; fixture.detectChanges(); }); fit('click confirm delete should delete the asset', fakeAsync(() => { // 创建新的SpyObj并替换组件内的服务引用 apiService = jasmine.createSpyObj('ApiService', ['get']); component.apiService = apiService; // 假设组件通过属性持有ApiService实例 apiService.get.and.returnValue(of({entity: ASSET} as unknown as HttpResponse<null>)); component.reload(); fixture.detectChanges(); // ... 点击删除按钮的逻辑 expect(component.asset).toBeFalsy(); expect(apiService.get).toHaveBeenCalled(); })); });
关键注意点
- 只有当服务实例是Jasmine SpyObj时,
spyOn才能正常工作,不要对TestBed.inject获取的真实服务实例直接调用spyOn。 - 推荐使用方法1,在
beforeEach中统一配置SpyObj,提升测试用例的复用性和可维护性。 - 若组件通过构造函数注入
ApiService,必须在TestBed配置中用SpyObj替换真实服务,否则组件初始化时会拿到真实实例,无法监听。
内容的提问来源于stack exchange,提问作者fritz6
相关产品推荐
相关产品推荐

