Angular测试:如何SpyOn私有属性UserManager并mock其getUser方法?
问题分析
你的核心问题是:AuthService里是直接通过new UserManager(config)创建实例,而非依赖注入获取,所以TestBed中配置的UserManager Spy完全没被用到,实际运行的是真实的UserManager实例,它会发起真实HTTP请求导致404错误。
解决方案
要拦截UserManager的构造函数,让服务中new UserManager()时返回我们的Spy对象,而非真实实例,具体步骤如下:
1. 调整测试前置配置(beforeEach)
根据UserManager的导入方式,选择对应的Spy拦截方式:
情况1:UserManager挂载在全局window对象
beforeEach(() => { // 1. 创建UserManager的Spy对象,mock getUser方法 const userManagerSpy = jasmine.createSpyObj('UserManager', ['getUser']); userManagerSpy.getUser.and.resolveTo(mockUser); // 2. 创建ConfigService的Spy const configSpy = jasmine.createSpyObj('ConfigService', ['getConfig']); configSpy.getConfig.and.returnValue(mockConfig); // 3. 拦截UserManager构造函数,返回Spy对象 spyOn(window, 'UserManager').and.returnValue(userManagerSpy); TestBed.configureTestingModule({ providers: [ AuthenticationService, { provide: ConfigService, useValue: configSpy } // 无需再提供UserManager,因为已拦截构造函数 ] }); authService = TestBed.inject(AuthenticationService); appConfigSpy = TestBed.inject(ConfigService) as jasmine.SpyObj<ConfigService>; });
情况2:从oidc-client模块导入UserManager
import * as oidcClient from 'oidc-client'; beforeEach(() => { // 1. 创建UserManager的Spy对象 const userManagerSpy = jasmine.createSpyObj('UserManager', ['getUser']); userManagerSpy.getUser.and.resolveTo(mockUser); // 2. 创建ConfigService的Spy const configSpy = jasmine.createSpyObj('ConfigService', ['getConfig']); configSpy.getConfig.and.returnValue(mockConfig); // 3. 拦截模块导出的UserManager构造函数 spyOn(oidcClient, 'UserManager').and.returnValue(userManagerSpy); TestBed.configureTestingModule({ providers: [ AuthenticationService, { provide: ConfigService, useValue: configSpy } ] }); authService = TestBed.inject(AuthenticationService); appConfigSpy = TestBed.inject(ConfigService) as jasmine.SpyObj<ConfigService>; });
2. 修正测试用例断言
原来的断言逻辑错误,需要验证构造函数调用和getUser方法调用:
it('should initialise the user manager and call getUser', async () => { // act await authService.load(); // assert // 验证UserManager构造函数被传入mockConfig调用 expect(window.UserManager).toHaveBeenCalledWith(mockConfig); // 或对应模块导入的情况:expect(oidcClient.UserManager).toHaveBeenCalledWith(mockConfig); // 验证getUser方法被调用 expect(userManagerSpy.getUser).toHaveBeenCalled(); });
关键说明
TestBed的providers配置仅对依赖注入的服务生效,而你的AuthService是自行创建UserManager实例,所以必须通过拦截构造函数的方式替换为Spy对象,才能避免真实HTTP请求。
内容的提问来源于stack exchange,提问作者atamata
相关产品推荐
相关产品推荐

