【问题标题】:How to write a unit test for angular routing with canActivate guard如何使用 canActivate 保护编写角度路由的单元测试
【发布时间】:2021-12-29 06:53:18
【问题描述】:

如何使用 canActivate 保护编写角度路由的单元测试?如果我在路线上使用 canActivate 防护,我会遇到错误。如果不是,则不会引发任何错误并通过测试。请帮我举个合适的例子,并解释一下。

app-routing.module.ts

export const routes: Routes = [
 { path: '', component: LoginComponent },
 { path: 'home', canActivate: [AuthGuard], component: HomeComponent },
 { path: '**', redirectTo: '/home' }
]

auth-guard.guard.ts

export class AuthGuard implements CanActivate {
  private auth: IAuth;

  constructor(
    private storageService: StorageService,
    private router: Router
  ){}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
      this.auth = JSON.parse(this.storageService.getLocalStorageItem('auth'));
      if(this.auth){
        return true;
      }

      this.router.navigate(['/'], {queryParams: {returnUrl: state.url}});
      return false;
  }
  
}

app-routing.module.test.ts

test(`Navigate to 'home' takes you to /home`, fakeAsync(() => {
        router.navigate(['/home']).then(() => {
            expect(location.path()).toEqual('/home');
        });
        flush();
    }));

测试结果

Testing Router › Navigate to 'home' takes you to /home

    Uncaught (in promise): Error: expect(received).toEqual(expected) // deep equality

    Expected: "/home"
    Received: "/"
    Error: expect(received).toEqual(expected) // deep equality

【问题讨论】:

    标签: javascript angular typescript jestjs jasmine


    【解决方案1】:

    您应该在运行测试之前为 AuthGuard.canActivate 传递 true。 这是一个 Jasmine 示例(进行调整):

    describe('Test Description', () => {
        ...
        beforeEach(() => {
           const canActivateStub = () => ({ canActivate: () => true });
           ... all your imports
           TestBed.configureTestingModule({
               ... (all your imports)
               providers: [
                   { provide: AuthGuard, useValue: canActivateStub}
               ]
           })
        })
        ...
    })
    

    对于 AuthGuard 测试单元,您可以这样做:

      describe('AuthGuard', () => {
            let service: AuthGuard;
        
        
            it('can load instance', () => {
                const routerStubInit = () => ({ navigate: (array, object) => ({}) });
                TestBed.configureTestingModule({
                    providers: [
                        AuthGuard,
                        HttpClient,
                        HttpHandler,
                        { provide: Router, useFactory: routerStubInit },
                    ]
                });
                service = TestBed.inject(AuthGuard);
        
                expect(service).toBeTruthy();
            });
        
            describe('canActivate', () => {
                it('makes expected calls', () => {
                    const authenticationServiceStub = () => ({ userValue: {} });
                    const routerStubInit = () => ({ navigate: (array, object) => ({}) });
                    TestBed.configureTestingModule({
                        imports: [HttpClientTestingModule],
                        providers: [
                            AuthGuard,
                            HttpClient,
                            HttpHandler,
                            { provide: Router, useFactory: routerStubInit },
                            { provide: AuthenticationService, useFactory: authenticationServiceStub }
                        ]
                    });
                    service = TestBed.inject(AuthGuard);
        
                    const activatedRouteSnapshotStub: ActivatedRouteSnapshot = <any>{};
                    const routerStateSnapshotStub: RouterStateSnapshot = <any>{};
                    spyOn(service, 'canActivate').and.callThrough();
                    service.canActivate(activatedRouteSnapshotStub, routerStateSnapshotStub);
                    expect(service.canActivate).toHaveBeenCalled();
                });
        
                it('makes expected calls', () => {
                    const routerStubInit = () => ({ navigate: (array, object) => ({}) });
                    const authenticationServiceStubNull = () => ({ userValue: null });
                    TestBed.configureTestingModule({
                        imports: [HttpClientTestingModule],
                        providers: [
                            AuthGuard,
                            HttpClient,
                            HttpHandler,
                            { provide: Router, useFactory: routerStubInit },
                            { provide: AuthenticationService, useFactory: authenticationServiceStubNull }
                        ]
                    });
                    service = TestBed.inject(AuthGuard);
        
                    const routerStub: Router = TestBed.inject(Router);
                    const activatedRouteSnapshotStub: ActivatedRouteSnapshot = <any>{};
                    const routerStateSnapshotStub: RouterStateSnapshot = <any>{};
                    spyOn(routerStub, 'navigate').and.callThrough();
                    service.canActivate(activatedRouteSnapshotStub, routerStateSnapshotStub);
                    expect(routerStub.navigate).toHaveBeenCalled();
                });
            });
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      • 1970-01-01
      • 2020-12-28
      • 2017-05-04
      • 1970-01-01
      • 1970-01-01
      • 2021-03-31
      相关资源
      最近更新 更多