Angular测试中如何对@Inject注入的服务执行SpyOn操作mock返回值
问题根源
你当前的配置存在两个核心问题:
- 令牌与实例不匹配:你在providers中同时注册了字符串令牌
'CategoryService'和类令牌MockCategoryService,两者对应完全独立的两个服务实例。你spy的是类令牌对应的实例,但组件实际注入的是字符串令牌对应的实例,spy自然不会生效。 - 执行顺序错误:你先调用了
TestBed.createComponent创建组件(此时组件构造函数已经执行,若构造函数或ngOnInit中已经调用了getCategories,后续spy不会覆盖已执行的逻辑),再执行spy操作,时机太晚。
解决方法
方法1:直接获取组件使用的服务实例进行spy(修改量最小)
不需要修改providers配置,直接调整测试代码顺序,获取字符串令牌对应的实例再spy即可:
beforeEach(() => { // 1. 先拿到组件实际使用的字符串令牌对应的服务实例 const categoryService = TestBed.inject<CategoryService>('CategoryService'); // 2. 先spy方法,再创建组件 spyOn(categoryService, 'getCategories').and.returnValue(of([{ id: 1, name: 'category01' }])); // 3. 最后创建组件、触发变更检测 fixture = TestBed.createComponent(ExpensesLayoutComponent); component = fixture.componentInstance; fixture.detectChanges(); });
方法2:统一令牌指向同一实例
修改providers配置,让字符串令牌和类令牌指向同一个实例,之后spy类令牌实例就会生效:
beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ExpensesLayoutComponent], providers: [ MockCategoryService, // 用useExisting指向已注册的MockCategoryService实例,两个令牌共享同一个实例 { provide: 'CategoryService', useExisting: MockCategoryService } ] }).compileComponents(); }); beforeEach(() => { mockCategoryService = TestBed.inject(MockCategoryService); // 先spy再创建组件 spyOn(mockCategoryService, 'getCategories').and.returnValue(of([{ id: 1, name: 'category01' }])); fixture = TestBed.createComponent(ExpensesLayoutComponent); component = fixture.componentInstance; fixture.detectChanges(); });
内容的提问来源于stack exchange,提问作者dmance
相关产品推荐
相关产品推荐

