Angular组件级注入服务时Jasmine不使用spyObject问题咨询
问题1:组件级提供服务时测试不生效的原因与解决方案
原因
Angular采用层级注入器机制,优先级从高到低为:组件级注入器 > 惰性模块注入器 > 根/测试模块注入器。你在组件的@Component.providers中声明了QueryThreadService,组件实例化时会优先从自身的注入器创建真实服务实例,你在TestBed.configureTestingModule中配置的mock服务属于测试模块级注入器,优先级更低,自然不会被组件使用。
测试用例编写方案
你可以通过Angular测试工具提供的overrideComponent方法,直接覆盖组件自身的providers配置,将组件级注入的服务替换为mock对象,修改后的测试初始化代码如下:
beforeEach(() => { queryThreadServiceSpyObj = jasmine.createSpyObj('QueryThreadService', ['getQueryThread']); TestBed.configureTestingModule({ providers: [ { provide: ActivatedRoute, useValue: { snapshot: { params: { accNumber: 1 } } } }, ] }) // 新增覆盖组件级服务的逻辑 .overrideComponent(QueryThreadComponent, { set: { providers: [ { provide: QueryThreadService, useValue: queryThreadServiceSpyObj } ] } }) .compileComponents(); fixture = TestBed.createComponent(QueryThreadComponent); component = fixture.componentInstance; component.query = { queryId: 1, entityAssignedTo: organisationName } as QueriesData; });
修改后组件就会加载你提供的spy对象,不会再实例化真实服务。
问题2:组件级提供服务是否为不良实践
组件级提供服务不是不良实践,反而符合Angular的服务隔离设计原则:
- 当服务仅对当前组件及其子组件可见,且每个组件实例需要独立的服务实例时,组件级提供是最优方案
- 你提到的1:1对应场景完全合理,这类服务通常是为对应组件定制的状态管理、业务逻辑封装层,不需要全局共享,组件销毁时对应的服务实例也会被自动销毁,不会造成内存泄漏
- 包括Angular Material在内的官方组件库也大量使用了组件级服务注入的设计,用来实现不同组件实例的状态隔离
唯一需要注意的就是这类组件的测试需要按照上述方案额外覆盖组件的providers配置,没有其他额外弊端。
内容的提问来源于stack exchange,提问作者tony09uk
相关产品推荐
相关产品推荐

