Angular 10-Guard单元测试

问题描述

我需要一个建议,如何使用某种逻辑来测试Guards,因为我有点困惑,如何在Jasmine / Karma中使用模拟/间谍:

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

    constructor(private credentials: CredentialsService,private router: Router) {
    }

    canActivate(route: ActivatedRouteSnapshot,routerState: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return this.credentials.getAuthorities().then(() => {
            if (!this.credentials.isGuestOrAdmin()) {
                this.router.navigate(['/sign-in'],{state: {url: routerState.url}});
            }
            return this.credentials.isGuestOrAdmin();
        });
    }
}

这是服务:

export class CredentialsService {
    authenticated: boolean = false;
    authorities: UserRole[];

    constructor(private router: Router,private authenticationService: AuthenticationService,private authorizationService: AuthorizationService,private notificationService: NotificationService) {
        this.getAuthorities().then();
    }

    public async getAuthorities() {
        await this.authorizationService.getAuthorities()
            .pipe(
                map(authorities => authorities.map(element => UserRole.getUserRoleType(element)))
            )
            .toPromise()
            .then(result => {
                this.authorities = result;
                this.authenticated = this.isNotAnonymous();
            })
            .catch(() => {
                this.authorities = [UserRole.ANONYMOUS];
                this.authenticated = this.isNotAnonymous();
            })
    }
}

模拟服务有可能吗?我使用Testbed.inject()尝试了很多事情,但没有成功。

软件版本:

  • 角度10.1.0,
  • 茉莉花核心3.6.0,
  • 业力5.2.1

解决方法

进行单元测试时,最好对要注入的所有服务进行模拟,以进行 unit 测试。服务应与所有其他组件分开测试。模拟服务时,您可以完全控制服务的方法返回什么。

在TestBed的提供程序中,您应该具有:

providers: [
  {
    provide: CredentialService,useValue: {
      getAuthorities: () => /* here what you want the getAuthorities method to return (apparently a promise) */,isGuestOrAdmin: () => /* true or false */
  }
]

如果在测试中需要更改 useValue 中定义的方法,则可以使用以下命令监视这些属性

spyOn(TestBed.get(CredentialService),'isGuestOrAdmin').and.returnValue(false);

例如。