Angular 16函数式守卫单元测试问题:未登录场景验证失败
Angular 16 函数式守卫未登录场景单元测试修正方案
问题根源
你当前的测试错误在于:executeGuard是守卫返回的函数实例,而非守卫执行后的返回值。直接断言一个函数等于false必然失败,因为函数本身是一个对象,不是布尔值。
修正后的测试代码
describe('authenticationGuard', () => { let cognitoServiceSpy: jasmine.SpyObj<CognitoService>; let userContextServiceSpy: jasmine.SpyObj<UserContextService>; let userServiceSpy: jasmine.SpyObj<UserService>; let mockRouter: jasmine.SpyObj<Router>; // 模拟路由快照参数 const mockRouteSnapshot = {} as ActivatedRouteSnapshot; const mockRouterStateSnapshot = { url: '/test' } as RouterStateSnapshot; beforeEach(() => { cognitoServiceSpy = jasmine.createSpyObj('CognitoService', ['currentAuthenticatedUser']); userServiceSpy = jasmine.createSpyObj('UserService', ['getCurrentUserInfos']); userContextServiceSpy = jasmine.createSpyObj('UserContextService', ['getUserInfos', 'setUserInfos']); mockRouter = jasmine.createSpyObj('Router', ['navigate']); // Mock localStorage 避免测试环境报错 spyOn(localStorage, 'setItem'); TestBed.configureTestingModule({ providers: [ { provide: CognitoService, useValue: cognitoServiceSpy }, { provide: UserService, useValue: userServiceSpy }, { provide: UserContextService, useValue: userContextServiceSpy }, { provide: Router, useValue: mockRouter } ] }); }); it('should redirect to login and return false when user is not authenticated', fakeAsync(async () => { // 模拟未登录状态 cognitoServiceSpy.currentAuthenticatedUser.and.resolveTo(false); // 获取守卫函数并执行 const guardFn = TestBed.runInInjectionContext(() => { return authenticationGuard(userContextServiceSpy); }); const result = await guardFn(mockRouteSnapshot, mockRouterStateSnapshot); // 验证断言 expect(localStorage.setItem).toHaveBeenCalledWith('redirect', JSON.stringify('/test')); expect(mockRouter.navigate).toHaveBeenCalledWith(['authentification']); expect(result).toBeFalse(); })); });
关键修正点
- 执行守卫函数:获取守卫返回的
guardFn后,必须调用它并传入ActivatedRouteSnapshot和RouterStateSnapshot参数,才能得到守卫的实际返回值。 - 处理异步逻辑:守卫是
async函数,返回Promise<boolean>,需要用await获取结果,结合fakeAsync确保异步逻辑完成。 - Mock localStorage:测试中调用了
localStorage.setItem,需要用spyOn模拟该方法,避免测试环境中出现未预期的副作用。 - 简化依赖注入:不需要额外提供
ActivatedRoute和RouterState,因为守卫执行时直接传入模拟的快照对象即可。
内容的提问来源于stack exchange,提问作者dna
相关产品推荐
相关产品推荐

