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

Angular Firebase组件测试:如何Mock user与signOut函数

解决Angular Fire Auth组件测试中的初始化检查错误

问题出在你直接使用了Angular Fire提供的user()和signOut()顶层函数,这两个函数内部会检查AngularFire模块的初始化状态,测试环境中没有配置完整的Firebase环境,所以触发了报错。你需要Mock这两个函数,而不是只MockAuth对象。

以下是两种常用测试框架下的解决方案:

方案一:使用Jest测试

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Auth } from '@angular/fire/auth';
import { FooComponent } from './foo.component';
import { Observable } from 'rxjs';

// Mock @angular/fire/auth模块的顶层函数
jest.mock('@angular/fire/auth', () => ({
  ...jest.requireActual('@angular/fire/auth'),
  // 返回空Observable,可根据测试需求替换为用户数据的Observable
  user: jest.fn(() => new Observable()),
  // 返回resolved Promise,模拟登出成功
  signOut: jest.fn(() => Promise.resolve()),
}));

describe('FooComponent', () => {
  let component: FooComponent;
  let fixture: ComponentFixture<FooComponent>;
  let mockAuth: Partial<Auth>;

  beforeEach(async () => {
    mockAuth = {};

    await TestBed.configureTestingModule({
      imports: [FooComponent],
      providers: [{ provide: Auth, useValue: mockAuth }],
    }).compileComponents();

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

  it('组件应正常创建', () => {
    expect(component).toBeTruthy();
  });

  it('调用logout方法时应触发signOut', async () => {
    const { signOut } = await import('@angular/fire/auth');
    await component.logout();
    expect(signOut).toHaveBeenCalledWith(mockAuth);
  });
});

方案二:使用Jasmine测试

import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { Auth, user, signOut } from '@angular/fire/auth';
import { FooComponent } from './foo.component';
import { of } from 'rxjs';

describe('FooComponent', () => {
  let component: FooComponent;
  let fixture: ComponentFixture<FooComponent>;
  let mockAuth: Partial<Auth>;
  let userSpy: jasmine.Spy;
  let signOutSpy: jasmine.Spy;

  beforeEach(async () => {
    mockAuth = {};
    
    // Mock user函数,返回空用户Observable
    userSpy = spyOn(require('@angular/fire/auth'), 'user').and.returnValue(of(null));
    // Mock signOut函数,模拟登出成功
    signOutSpy = spyOn(require('@angular/fire/auth'), 'signOut').and.returnValue(Promise.resolve());

    await TestBed.configureTestingModule({
      imports: [FooComponent],
      providers: [{ provide: Auth, useValue: mockAuth }],
    }).compileComponents();

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

  it('组件应正常创建', () => {
    expect(component).toBeTruthy();
  });

  it('调用logout时应传入Auth实例调用signOut', fakeAsync(() => {
    component.logout();
    tick(); // 等待Promise执行完成
    expect(signOutSpy).toHaveBeenCalledWith(mockAuth);
  }));
});

关键说明

  • 必须Mockuser和signOut这两个顶层函数,因为组件直接调用了它们,而非依赖注入的服务实例。
  • user函数需要返回Observable类型的值,确保组件中this.user的订阅逻辑正常运行。
  • signOut函数需要返回resolved状态的Promise,保证logout方法能正常完成。
  • 无需导入AngularFireModule,Mock函数后会绕过内部的初始化检查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:44:58