Angular 5单元测试路线与防护

时间:2018-05-24 12:03:52

标签: angular karma-jasmine

我有一条路线需要阻止学生访问。我正在尝试为此编写单元测试,但它无法正常工作。

我对守卫本身的单元测试工作正常,但是当我尝试编写一个导航到/ class的测试时,防护上的canActivate方法不会被调用。

这是警卫:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
  const user = StoreActions.User.getCurrentUser(store.getState());

  if(!user) {
    this.router.navigate(['/pages/login']);
    return false;
  }

  if(user.username.match(/\d/) !== null) {
    this.router.navigate(['/home']);
    return false;
  }

  return true;
}

测试:

it(
  'should activate guard when a student tries to access /class',
  fakeAsync(
    inject([StudentGuard], (guard: StudentGuard) => {
      const spy = spyOn(guard, 'canActivate');
      store.dispatch(StoreActions.User.setCurrentUser(TestObjects.User.Student));
      router.navigate(['/class/1']);
      tick();
      expect(spy).toHaveBeenCalled();
      discardPeriodicTasks();
    })
  )
);

以下是具体路线:

{
  path: '',
  children: {
    path: 'class',
    loadChildren: './components/class/class.module#ClassModule',
    canActivate: [StudentGuard]
  }
}

expect语句在测试中失败。但是,如果我实际上冒充学生,然后导航到浏览器中的/ class,则防护按预期工作,但它不会在测试中激活。如何在测试中激活它?

1 个答案:

答案 0 :(得分:1)

我只是想通了。我发现了几个类似的问题,说业力正在等待一个可观察的问题得到解决。我意识到router.navigate会返回一个承诺,业力必须等待解决。我不得不改变我的测试:

it(
  'should activate guard when a student tries to access /class',
  fakeAsync(
    inject([StudentGuard], (guard: StudentGuard) => {
      const spy = spyOn(guard, 'canActivate');
      store.dispatch(StoreActions.User.setCurrentUser(TestObjects.User.Student));
      router.navigate(['/class/1']).then(() => { // added .then
          expect(spy).toHaveBeenCalled(); // put expect here, AFTER navigate is resolved
      });
      tick();
      discardPeriodicTasks();
    })
  )
);