我有一个AuthGuard
服务负责检测用户是否已登录。如果没有登录,我会将用户重定向到我们的oauth提供商网址。
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { environment } from './../../environments/environment';
import { Session } from './../core/security/session.service';
@Injectable()
export class AuthGuard implements CanActivate {
/**
* Class constructor.
* @constructor
*
* @param {Session} - Instance of session.
*/
constructor(private session: Session) {}
/**
* Method to implements from CanActivate interface.
* Check if a user is authenticated.
*
* @return {boolean}
*/
canActivate(): boolean {
if (this.session.isActive()) {
return true;
}
this.redirectToProvider();
return false;
}
/**
* Redirect to Identity unauthorized url.
*/
private redirectToProvider() {
const unauthorizeUrl = environment.api.identity.unauthorizeUrl;
window.location.href = unauthorizeUrl;
}
}
我想知道当Session不存在时是否调用window.location.href
。这是我到目前为止所做的:
import { TestBed, async, inject } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AuthGuard } from './auth-guard.service';
import { Session } from './../core/security/session.service';
describe('AuthGuard', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
AuthGuard,
Session
],
imports: [RouterTestingModule]
});
});
describe('.canActivate', () => {
describe('active session', () => {
it('returns true',
async(inject([AuthGuard, Session], (guard, session) => {
session.set({ name: 'user' });
expect(guard.canActivate()).toBeTruthy();
})
));
});
describe('no session', () => {
it('redirects the user',
async(inject([AuthGuard, Session], (guard, session) => {
spyOn(window.location, 'href');
session.destroy();
expect(guard.canActivate()).toBeFalsy();
expect(window.location.href).toHaveBeenCalled();
})
));
});
})
});
但是它给了我以下错误:
Failed: <spyOn> : href is not declared writable or has no setter
有没有办法模拟窗口对象来实现这一点,还是我需要依赖一些特殊的类来处理这样的重定向,以便我可以在测试中注入它们?
答案 0 :(得分:1)
您可以注入environment.dev.ts
作为注入令牌。 Angular在@ angular / common中还有一个window
DI令牌,您可以直接与DOCUMENT
一起使用。
document.location.href
将其添加到import { InjectionToken } from '@angular/core';
export const WindowToken = new InjectionToken('Window');
export function windowProvider() { return window; }
:
app.module.ts
并将其注入服务中
providers: [
...
{ provide: WindowToken, useFactory: windowProvider }
]
在您的spec文件中,模拟window对象并对其进行测试。我创建了一个具有两个测试服务的工作示例(一个依赖于另一个)。该服务是使用Angular的Static Injector创建的:
constructor(@Inject(WindowToken) private window: Window, private session: Session)