AngularFireAuth模拟问题:AuthService单元测试注入错误排查
解决AngularFireAuth注入错误及正确模拟实现
问题背景
我封装了AuthService统一处理AngularFireAuth的认证逻辑,但在执行基础的toBeTruthy断言时触发了注入错误。之前用简单模拟解决过其他组件的同类问题,但针对AngularFireAuth的复杂模拟卡壳了。
原始错误
NullInjectorError: R3InjectorError(DynamicTestModule)[AuthService -> AngularFireAuth -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]:
当前测试代码(auth.service.spec.ts)
import { TestBed } from '@angular/core/testing'; import { AuthService } from './auth.service'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { AngularFireAuth } from '@angular/fire/compat/auth'; import { AngularFirestoreMock } from '../../testing/mock_angularFirestore'; import { AngularFireAuthMock } from '../../testing/mock_angularFireAuth'; describe('AuthService', () => { let service: AuthService; beforeEach(() => { TestBed.configureTestingModule( { providers: [ {provide: AngularFirestore, useValue: AngularFirestoreMock}, {provide: AngularFireAuth, useVallue: AngularFireAuthMock} // 存在拼写错误:useVallue → useValue ] }); service = TestBed.inject(AuthService); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
已实现的有效模拟
AngularFirestoreMock
export const AngularFirestoreMock = { set: () => {} };
AuthServiceMock
export const AuthServiceMock = jasmine.createSpy('userData') .and.returnValue(Promise.resolve({ uid: 'fakeuser', email: 'test@test.com', emailVerified: true }));
需要模拟的AngularFireAuth方法及返回值
authState.subscribe():返回Observable<User | null>(注意不是Promise)createUserWithEmailAndPassword:PromisesendEmailVerification:PromisesignOut:PromisesignInWithEmailAndPassword:PromisesendPasswordResetEmail:PromisecurrentUser:在compat版本中是**Promise<User | null>**类型的属性
正确的AngularFireAuthMock实现
import { of } from 'rxjs'; import { UserCredential } from '@angular/fire/auth'; // 模拟用户对象 const mockUser = { uid: 'fakeuser', email: 'test@test.com', emailVerified: true, sendEmailVerification: () => Promise.resolve() }; // 模拟UserCredential const mockUserCredential: Partial<UserCredential> = { user: mockUser, credential: null }; export const AngularFireAuthMock = jasmine.createSpyObj('AngularFireAuth', [ 'createUserWithEmailAndPassword', 'signOut', 'signInWithEmailAndPassword', 'sendPasswordResetEmail' ], { // 属性模拟 authState: of(mockUser), // authState是Observable,用of包装模拟值 currentUser: Promise.resolve(mockUser) }); // 给每个方法设置返回值 AngularFireAuthMock.createUserWithEmailAndPassword.and.returnValue(Promise.resolve(mockUserCredential as UserCredential)); AngularFireAuthMock.signOut.and.returnValue(Promise.resolve()); AngularFireAuthMock.signInWithEmailAndPassword.and.returnValue(Promise.resolve(mockUserCredential as UserCredential)); AngularFireAuthMock.sendPasswordResetEmail.and.returnValue(Promise.resolve());
关键修正点
- 拼写错误修复:测试代码里的
useVallue改为useValue,这是导致注入失败的直接原因之一。 - authState类型修正:authState是Observable而非Promise,要用
rxjs的of创建模拟流。 - 方法拼写修正:把错误的
signout改为正确的signOut。 - 返回值匹配类型:确保每个方法的返回值和AngularFireAuth的实际类型一致,比如
sendEmailVerification返回空Promise,而非带错误码的对象。 - currentUser模拟:compat版本中currentUser是Promise类型的属性,直接返回Promise.resolve(mockUser)即可。
内容的提问来源于stack exchange,提问作者Rusty Shackleford
相关产品推荐
相关产品推荐

