Angular如何测试私有变量方法调用?验证ngOnDestroy时unsubscribe执行
如何测试Angular组件中ngOnDestroy时私有Subscription的unsubscribe调用?
看起来你在测试LoaderMask组件的ngOnDestroy钩子时踩了个小坑——想验证私有subscription的unsubscribe方法是否被调用,结果遇到了spyOn找不到对象的错误。我来帮你分析下原因,再给出解决办法。
问题根源
报错的核心原因很直接:在你执行spyOn(component['subscription'], 'unsubscribe')时,component['subscription']还是undefined。因为组件的ngOnInit方法还没被调用,subscription变量根本没被赋值,spyOn自然找不到可以监听的对象。
解决方案
这里有两种靠谱的解决思路,你可以根据测试场景选择:
方案1:模拟组件初始化流程(更贴近真实场景)
先调用ngOnInit让subscription被正确初始化,同时需要提前mockloaderService的loaderState Observable,确保它能返回一个可订阅的对象:
it('should destroy the subscription when destroying', () => { // 先mock loaderService的loaderState,返回一个带unsubscribe方法的订阅对象 const mockSubscription = { unsubscribe: jasmine.createSpy('unsubscribe') }; spyOn(loaderService.loaderState, 'subscribe').and.returnValue(mockSubscription); // 调用ngOnInit初始化组件的subscription变量 component.ngOnInit(); // 现在subscription已经存在,可以监听unsubscribe方法了 const spyUnSubscribe = spyOn(component['subscription'], 'unsubscribe'); // 触发ngOnDestroy component.ngOnDestroy(); // 验证unsubscribe被调用 expect(spyUnSubscribe).toHaveBeenCalled(); });
方案2:手动赋值mock订阅对象(更直接)
如果只需要测试ngOnDestroy里的逻辑,不想依赖ngOnInit的执行,可以直接创建一个mock的Subscription对象,手动赋值给私有变量:
it('should destroy the subscription when destroying', () => { // 创建一个带spy的mock订阅对象 const mockSubscription = { unsubscribe: jasmine.createSpy('unsubscribe') }; // 手动赋值给组件的私有subscription变量 component['subscription'] = mockSubscription as unknown as Subscription; // 触发ngOnDestroy component.ngOnDestroy(); // 验证unsubscribe被调用 expect(mockSubscription.unsubscribe).toHaveBeenCalled(); });
额外提醒
原测试里的expect(component['subscription']).toBeUndefined();其实是不正确的——你的组件代码里只调用了unsubscribe(),并没有把subscription设为undefined,这个断言会导致测试失败,建议移除或者修改成符合组件逻辑的断言。
内容的提问来源于stack exchange,提问作者NICO
相关产品推荐
相关产品推荐

