Angular单元测试如何Mock Overlay、OverlayRef与Injector依赖
Angular PopupService 单元测试依赖Mock问题
你编写的PopupService服务实现代码如下:
@Injectable() export class PopupService { private _modal: ModalRef | null = null; constructor(private overlay: Overlay, private readonly overlayRef: OverlayRef, private parentInjector: Injector) {} open(data: PopupConfig) { const overlayRef = this.overlay.create(this._getModalConfig()); const modalRef = newModalRef(overlayRef); const injector = this._getInjector(data, modelRef, this.parentInjector); const portal = new ComponentPortal(PopupComponent, null, injector); overlayRef.attach(portal); return modalRef; } }
你在为该服务编写单元测试时,不清楚如何在测试的providers配置中MockOverlay、OverlayRef、Injector三个依赖,运行测试时抛出No provider for PopupService报错。
你初步设想的providers配置如下:
providers: [ Overlay,{provider: Overlay, useValue: fakeOverlay}, OverlayRef, {provide: OverlayRef, useValue: fakeOverlayRef}, Injector, {provider: Injector, useValue: fakeInjector} ]
你设想通过jasmine.createSpyObj创建三个间谍对象作为模拟值,对应代码如下:
const fakeOverlay = jasime.createSpyObj('Overlay', []); const fakeOverlayRef = jasime.createSpyObj('OverlayRef', []); const fakeInjector = jasime.createSpyObj('Injector', []);
写法问题说明
你的模拟思路整体方向是对的,但存在几处错误导致测试运行失败:
- 核心报错原因:测试的
providers数组中没有加入你要测试的PopupService本身,Angular测试床找不到该服务的注册项就会抛出No provider for PopupService错误。 - 配置写法错误:
providers中同时写原始类名和mock提供项属于重复配置,且存在拼写错误:provider应为provide。 - 模拟对象创建错误:创建间谍对象的方法名拼写错误,
jasime正确写法为jasmine;且创建spy对象时没有把业务代码中会调用到的对应方法加入方法列表,运行时会触发"xxx is not a function"错误。
正确写法参考
1. 创建Mock依赖对象
// 声明mock对象,把业务中调用到的方法加入第二个参数的方法数组 const fakeOverlay = jasmine.createSpyObj<Overlay>('Overlay', ['create']); const fakeOverlayRef = jasmine.createSpyObj<OverlayRef>('OverlayRef', ['attach']); const fakeInjector = jasmine.createSpyObj<Injector>('Injector', []); // 提前定义方法返回值,匹配业务逻辑 fakeOverlay.create.and.returnValue(fakeOverlayRef);
2. 配置测试模块的Providers
providers: [ PopupService, // 必须注册待测试的服务本身 { provide: Overlay, useValue: fakeOverlay }, { provide: OverlayRef, useValue: fakeOverlayRef }, { provide: Injector, useValue: fakeInjector } ]
额外注意事项
- 你贴出的服务业务代码本身存在笔误:
newModalRef应为实例化ModalRef的正确写法,open方法中传入_getInjector的modelRef是拼写错误,应为modalRef,这两处问题会导致业务代码本身运行报错,需要先修正。 - 如果后续需要验证服务逻辑,可以通过spy对象的断言方法校验调用参数是否正确,比如验证
fakeOverlay.create是否传入了符合预期的弹窗配置、fakeOverlayRef.attach是否传入了正确创建的组件门户实例。
内容的提问来源于stack exchange,提问作者Bigeyes
相关产品推荐
相关产品推荐

