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); })); });
关键说明
- 必须Mock
user和signOut这两个顶层函数,因为组件直接调用了它们,而非依赖注入的服务实例。 user函数需要返回Observable类型的值,确保组件中this.user的订阅逻辑正常运行。signOut函数需要返回resolved状态的Promise,保证logout方法能正常完成。- 无需导入AngularFireModule,Mock函数后会绕过内部的初始化检查。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

