angular - 如何将 Angular 6+ 服务变量注入(inject) app-routing.module.spec.ts 并测试路由器重定向

标签 angular unit-testing jasmine angular-test

如果 authenticated 变量设置为 true,我正在尝试测试用户是否成功重定向。

我已经尝试将我的 LoginService 注入(inject)到 beforeEach 并将 authenticated 变量设置为 false。然后,在单元测试中,将该变量设置为 true。然后,我希望我的 guard 发现 authenticated 设置为 true 的事实,然后重定向到仪表板页面。

应用程序路由模块.spec.ts:

import { LoginService } from './services/login.service';
import { Router } from "@angular/router";
import { RouterTestingModule } from '@angular/router/testing';
import { Location } from "@angular/common";
import { routes } from "./app-routing.module";
import { AppComponent } from './components/app.component';


describe('AppRoutingModule, () => {
      let location: Location;
      let router: Router;

  beforeEach(() => {
      TestBed.configureTestingModule({
          declarations: [AppComponent],
          providers: [LoginService]
      })

      router = TestBed.get(Router);
      location = TestBed.get(Location);
      fixture = TestBed.createComponent(AppComponent);
      router.initialNavigation();
  });

  beforeEach(inject([LoginService], (loginService: LoginService) => {
    loginService.authenticated = false;
  }))

  it('should redirect the user form the LoginComponent to the DashboardComponent if the user is already logged in', inject([LoginService](loginService: LoginService) => {
    loginService.authenticated = true;
    console.log(loginService);
    router.navigate([""]).then(() => {
      expect(location.path()).toBe("/dashboard");
    });
  }))
})

登录.guard.ts:

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { LoginService } from '../services/login.service';
import { Observable } from 'rxjs/index';


@Injectable({
  providedIn: 'root'
})
export class LoginGuard implements CanActivate {

  constructor(private router: Router, private loginService: LoginService) { 
}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    console.log('checked authenticated guard');
    if (this.loginService.authenticated === true) {
      this.loginService.navigationState.next(true);
      return true;
    } else {
      this.router.navigate(['']);
      return false;
    }
  }
}

登录服务.ts:

public authenticated = false;

应用程序路由.module.ts:

export const routes: Routes = [
  { path: '', component: LoginComponent },
  { path: 'dashboard', component: CurrentActivityComponent, canActivate: [LoginGuard] }
]

我希望测试通过,将用户重定向到“仪表板”,但它失败了:Expected '/' to be '/dashboard'。

我怀疑这与我注入(inject)服务的方式有关。但我不确定我做错了什么。

最佳答案

在您的测试中,您正在导航到根本没有守卫的主要路线 (router.navigate([""]))(换句话说,您的守卫没有被调用)。只有当您实际尝试访问 protected 路线时,才会调用守卫。因此,在您的测试中,您必须导航到仪表板 (router.navigate(['dashboard'])) 才能通过。

要实现您所描述的重定向行为,您必须为此目的向第一条路线添加另一个守卫。

PS:Jasmine 还带有 spy ,可以让你 f.i.通过指定服务方法的返回值,将组件测试与服务实现分离。但是它们不适用于普通属性(没有 getter/setter)。如果您的服务有 isAuthenticated 方法,它看起来像这样:

const loginService = fixture.debugElement.injector.get(LoginService);
spyOn(loginService, 'isAuthenticated').and.returnValue(true);

spy 在每个 IT block 的范围内,这意味着它们对您的其他测试没有任何副作用。

关于angular - 如何将 Angular 6+ 服务变量注入(inject) app-routing.module.spec.ts 并测试路由器重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54630536/

相关文章:

angular - 应该对所有事情都使用 ChangeDetectionStrategy.OnPush 吗?

Angular 6验证数字输入

javascript - 如何在 tsconfig.json 中排除以 '.spec.ts' 结尾的文件

angularjs - Angular Jasmine 测试响应拦截器

ajax - Jasmine 2.0 如何处理ajax请求

javascript - 跨不同容器 div 的 ngFor 数据长度为 4

.net - 模拟框架的新手

Python mockito - 模拟一个从可测试函数实例化的类

c++ - 有没有办法在 QT 中对 UI 应用程序进行单元测试

angular - 导入 json 文件以模拟我的测试数据