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

Jasmine测试报错:点击登录按钮后Mock AuthService方法未触发排查

问题描述

刚开始用Jasmine,想创建Mock AuthService,期望点击表单按钮后触发点击处理器,进而调用Mock服务的方法,但测试报错:

Error: : Expected a spy, but got Object({ authUser: spy on AuthService.authUser }). Usage: expect().toHaveBeenCalled()

之前手动传参调用方法的测试正常,现在要实现按钮触发的完整流程,相关代码如下:

测试代码

describe('Login submit', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
    TestBed.configureTestingModule({
      providers: [
        AuthService,
        HttpClientTestingModule,
        HttpClientModule,
        HttpClient,
        HttpHandler,
        MatSnackBar,
        Overlay,
        FormBuilder,
      ],
    });
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
 it('authService should launch', () => {
    let mockAuthService = jasmine.createSpyObj('AuthService', ['authUser']);
    const mockUser = { usernsme: 'Marcus', password: 'Marcus#1' };
    const compiled = fixture.debugElement;
    const loginBtn = compiled.query(By.css('.login-btn')).nativeElement;
    loginBtn.dispatchEvent(new Event('click'));
    expect(mockAuthService).toHaveBeenCalled();
  });
});

LoginComponent的userLoginClick方法

userLoginClick() {
    if (!this.form.valid) {
      this.pushNotificationService.createNotification(
        'Data format is incorrect'
      );

      return false;
    }
    const user = {
      username: this.form.controls['username'].value,
      password: this.form.controls['password'].value,
    };

    this.authService.authUser(user);
  }

AuthService的authUser方法

authUser(user: User) {
    return this.http
      .post(
        `${environment.domain}${BackendRoutes.Login}`,
        user,
        this.httpOptions
      )
      .subscribe((data: any) => {
        if (!data.success) {
          this.pushNotificationService.createNotification(data.message);
        } else {
          this.router.navigate([`/${Paths.Lobby}`]);
          this.storeUser(data.token, data.user);
        }
      });
  }

问题原因及修复方案

核心问题

  1. Mock服务没注入组件:你创建了mockAuthService但没替换TestBed里的真实AuthService,组件用的还是原始服务实例,根本没用到你写的Spy对象。
  2. 断言对象错了:expect(mockAuthService).toHaveBeenCalled()是对整个Spy对象做断言,但你要验证的是对象里的authUser方法,应该断言这个方法。
  3. 表单状态无效:点击按钮时表单控件是空的,会触发校验失败直接返回,根本走不到调用authUser的逻辑。

修正后的测试代码

describe('Login submit', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let mockAuthService: jasmine.SpyObj<AuthService>;

  beforeEach(async () => {
    // 创建AuthService的Spy对象
    mockAuthService = jasmine.createSpyObj('AuthService', ['authUser']);

    await TestBed.configureTestingModule({
      imports: [HttpClientTestingModule], // 测试环境只需要这个,其他冗余依赖可以删掉
      providers: [
        { provide: AuthService, useValue: mockAuthService }, // 用Mock替换真实服务
        MatSnackBar,
        Overlay,
        FormBuilder,
      ],
    }).compileComponents(); // 异步编译组件(如果用了 templateUrl 必须加)

    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    // 给表单控件赋值,确保表单校验通过
    component.form.patchValue({
      username: 'Marcus',
      password: 'Marcus#1'
    });
    fixture.detectChanges(); // 触发变更检测,更新表单状态
  });

  it('should call authService.authUser when login button is clicked', () => {
    const loginBtn = fixture.debugElement.query(By.css('.login-btn')).nativeElement;
    loginBtn.dispatchEvent(new Event('click'));
    fixture.detectChanges(); // 触发点击后的变更检测

    // 断言authUser方法被调用
    expect(mockAuthService.authUser).toHaveBeenCalled();
    // 可选:校验传入的参数是否正确
    expect(mockAuthService.authUser).toHaveBeenCalledWith({
      username: 'Marcus',
      password: 'Marcus#1'
    });
  });
});

额外说明

  • 去掉了HttpClientModule、HttpClient这类冗余依赖,测试环境用HttpClientTestingModule足够。
  • 调用compileComponents()确保异步组件编译完成,避免组件未加载完全的问题。
  • 通过patchValue给表单赋值,保证userLoginClick里的校验逻辑能通过,顺利调用authUser。
  • 把断言目标改成mockAuthService.authUser,这才是你创建的Spy方法,符合Jasmine的断言规则。

内容的提问来源于stack exchange,提问作者Vova Aleshchenko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:15:43