You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 09:00:34