![](/img/trans.png)
[英]How to use Jest to write a unit test for canActivate Angular guards
[英]How to unit test canActivate of Angular?
如何測試canActivate
函數,該函數返回一個函數,該函數又返回一個boolean
值?
我嘗試創建ActivatedrouterSnapshot
和routerStateSnapshot
對象並將其傳遞給canActivate
函數,但這沒有幫助。
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthenticationService,
private loginService: LoginService,
private router: Router
) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean>
| boolean {
return this.checkLogin(state.url);
}
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn()) { return true; }
// Store the attempted URL for redirecting
this.loginService.redirectUrl = url;
// Navigate to the login page with extras
this.router.navigate(['/login']);
return false;
}
}
由於checklogin
返回true
,我希望發生這種情況。 但我不知道從哪里開始?
有很多方法可以做到這一點。 我會建議類似以下內容。 只是為了展示一些多樣性,我用一個類模擬了一個服務,用一個 spyObject 模擬了另一個服務。
這是建議的代碼:
class LoginMock implements Partial<LoginService> {
redirectUrl: string;
}
describe('AuthGuard', () => {
let authGuard: AuthGuard;
let loginService: LoginMock;
const routerMock = jasmine.createSpyObj('Router', ['navigate']);
const authMock = jasmine.createSpyObj('AuthenticationService', ['isLoggedIn']);
beforeEach(() => {
loginService = new LoginMock();
authGuard = new AuthGuard(authMock, loginService, routerMock);
});
it('should be createable', () => expect(authGuard).toBeTruthy());
it('should return true for canActivate() and not set loginService.redirectUrl when isLoggedIn === true', ()=> {
authMock.isLoggedIn.and.returnValue(true);
const result = authGuard.canActivate(new ActivatedRouteSnapshot(), <RouterStateSnapshot>{url: 'testUrl'});
expect(result).toBe(true);
expect(loginService.redirectUrl).toBeUndefined();
});
it('should return false for canActivate() and set loginService.redirectUrl when isLoggedIn === false', ()=> {
authMock.isLoggedIn.and.returnValue(false);
const result = authGuard.canActivate(new ActivatedRouteSnapshot(), <RouterStateSnapshot>{url: 'testUrl'});
expect(result).toBe(false);
expect(loginService.redirectUrl).toEqual('testUrl');
});
});
我已經為你把它放在了一個Stackblitz中。 隨意將其分叉到您自己的 Stackblitz 環境中並進行修改。
祝你好運。 :)
在這個電暈日,我在辦公室所能做的就是為某些應用程序進行單元測試。 我做的最后一個測試是一個 canActivate 服務,它看起來像這樣:
import {Injectable} from "@angular/core";
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from "@angular/router";
import {UserProvider} from "../core/app-initializers/user-provider.service";
import {permissionsList} from "../shared/models/permissions.model";
@Injectable()
export class CreateArrangementPermissionService implements CanActivate {
constructor(private router: Router, private userProvider: UserProvider) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if(route.params.idOrCreationKeyWord && route.params.idOrCreationKeyWord == 'create') {
if (this.userProvider.getConnectedUsersApplicativeRoles().indexOf(permissionsList.DECLARANT) < 0) {
this.router.navigate(['/forbidden']);
return false;
}
}
return true;
}
}
我已經寫了測試:
import { CreateArrangementPermissionService } from "./create-arr-permission-service";
import { TestBed, getTestBed } from "@angular/core/testing";
import { UserProvider } from "../core/app-initializers/user-provider.service";
import { Router } from "@angular/router";
describe('CreateArrangementPermissionService Unit tests', () => {
let injector: TestBed;
let userProvider = {
getConnectedUsersApplicativeRoles: function() {
return 'zorro'
}
};
let guard: CreateArrangementPermissionService;
let routeMock: any = {
snapshot: {},
params: {
idOrCreationKeyWord: 'create'
}
};
let routerStateMock: any = {
snapshot: {},
url: '/forbidden'
};
let routerMock = {
navigate: jasmine.createSpy('navigate')
};
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: UserProvider, useValue: userProvider},
{ provide: Router, useValue: routerMock },
AuthenticationErrorHandler,
AuthenticationErrorCommunicator,
CreateArrangementPermissionService,
]
});
injector = getTestBed();
userProvider = injector.get(UserProvider);
guard = injector.get(CreateArrangementPermissionService)
});
it('should redirect an unauthenticated user to forbidden', () => {
expect(guard.canActivate(routeMock, routerStateMock)).toEqual(false);
expect(routerMock.navigate).toHaveBeenCalledWith(['/forbidden'])
});
it('should allow the authenticated user to access app', () => {
let routeMockAdmin: any = {
snapshot: {},
params: {
idOrCreationKeyWord: 'TPRM_ADMINISTRATOR'
}
};
expect(guard.canActivate(routeMockAdmin, routerStateMock)).toEqual(true);
});
});
通過這個測試,我在 SonarQube 上獲得了 89.5% 的覆蓋率,缺少對構造函數和“indexOf()”的一些測試。 希望這個例子能幫助其他人更容易地對 canActivate 進行正確的測試,然后我自己進行實驗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.