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

Angular单元测试:如何用spyOnProperty将Mock的userData设为null

解决Angular测试中动态设置Mock属性值的问题

针对你遇到的无法在测试中动态修改AuthServiceMock的userData属性的问题,提供以下几种可行方案:

方案1:将Mock的userData改为Getter属性

修改原AuthServiceMock,把userData改成Getter属性,这样就能通过spyOnProperty控制返回值:

import { User } from "../shared/interface/user";

const authState: User = {
  uid: 'fakeuser',
  email: 'test@test.com',
  emailVerified: true
};

export const AuthServiceMock = {
  ForgotPassword: () => {},
  SignUp: () => {},
  // 改为Getter属性
  get userData() {
    return authState;
  }
};

对应的测试代码:

it('Text Not Rendered - No User Data', () => {
  // 获取注入的AuthService实例
  const authService = TestBed.inject(AuthService);
  // 监视userData的Getter,返回null
  spyOnProperty(authService, 'userData', 'get').and.returnValue(null);
  
  // 触发变更检测,更新ngIf状态
  fixture.detectChanges();
  
  const compiled = fixture.nativeElement as HTMLElement;
  // 确认目标元素不存在
  expect(compiled.querySelector('#confirmText')).toBeNull();
});

方案2:直接修改Mock的属性值(无需修改原Mock)

由于TestBed使用useValue传入的是Mock对象的引用,可直接修改其userData属性,再触发变更检测:

it('Text Not Rendered - No User Data', () => {
  // 获取注入的AuthService实例并断言类型
  const authService = TestBed.inject(AuthService) as typeof AuthServiceMock;
  // 直接将userData设为null
  authService.userData = null;
  
  // 触发变更检测
  fixture.detectChanges();
  
  const compiled = fixture.nativeElement as HTMLElement;
  expect(compiled.querySelector('#confirmText')).toBeNull();
});

注意:若多个测试存在属性值干扰,需在beforeEach中重置userData:

beforeEach(async () => {
  await TestBed.configureTestingModule({
    declarations: [VerifyEmailAddressComponent],
    providers: [{ provide: AuthService, useValue: AuthServiceMock }]
  }).compileComponents();

  fixture = TestBed.createComponent(VerifyEmailAddressComponent);
  component = fixture.componentInstance;
  // 重置userData为初始值
  const authService = TestBed.inject(AuthService) as typeof AuthServiceMock;
  authService.userData = {
    uid: 'fakeuser',
    email: 'test@test.com',
    emailVerified: true
  };
  fixture.detectChanges();
});

方案3:使用useFactory创建独立Mock实例

为避免测试间互相影响,用useFactory为每个测试生成独立的Mock对象:

beforeEach(async () => {
  await TestBed.configureTestingModule({
    declarations: [VerifyEmailAddressComponent],
    providers: [
      { 
        provide: AuthService, 
        useFactory: () => ({
          ForgotPassword: () => {},
          SignUp: () => {},
          userData: {
            uid: 'fakeuser',
            email: 'test@test.com',
            emailVerified: true
          }
        })
      }
    ]
  }).compileComponents();

  fixture = TestBed.createComponent(VerifyEmailAddressComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

每个测试都会得到全新的Mock实例,修改userData不会影响其他测试,测试代码同方案2。

内容的提问来源于stack exchange,提问作者Rusty Shackleford

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:06:19