问题描述
我构建了一个小型 Angular 应用程序,现在我正在编写单元测试.到目前为止一切顺利,但是当我尝试测试我的 authGuard 时,我遇到了一些问题.我正在使用 观众.我在规范的提供者部分提供了 platformId,但我希望能够覆盖它,以便我可以测试值服务器"和浏览器"的场景我的代码用于 authGuard:
I built a small angular app and now I'm writing unit tests. So far so good, but when I try to test my authGuard I ran into some problems. I am using Spectator.I provide the platformId in the providers section in my spec, but I want to be able to overwrite it so I can test scenarios where for values 'server' as well as 'browser'My code is for the authGuard:
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router,
@Inject(PLATFORM_ID) private platformId: Object,
) {}
canActivate(
_route: ActivatedRouteSnapshot,
_state: RouterStateSnapshot,
): boolean | UrlTree | Promise<boolean | UrlTree> | Observable<boolean | UrlTree> {
if (isPlatformServer(this.platformId)) {
console.log('server');
return true;
} else {
console.log('browser');
this.authService.autoLogin();
return this.authService.user.pipe(
take(1),
map((user) => {
console.log('user', user);
if (!!user) {
return true;
}
console.log('navugate');
this.router.navigate(['/auth']);
return false;
}),
);
}
}
}
和规范文件:
describe('AuthGuard', () => {
let spectator: SpectatorService<AuthGuard>;
const config = {
service: AuthGuard,
imports: [RouterTestingModule, HttpClientTestingModule],
providers: [AppRoutingModule, AuthService, { provide: PLATFORM_ID, useValue: 'server' }],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
};
const createService = createServiceFactory(config);
// some other tests here ....
it('should should navigate to /auth if running on browser and not authenticated', () => {
config.providers = [AppRoutingModule, { provide: PLATFORM_ID, useValue: 'browser' }];
spectator = createService();
const spyNavigate = spyOn(spectator.service['router'], 'navigate').and.callThrough();
const user = new User('bla@bla.com', 'id', 'token', new Date(10000));
spectator.service['authService'].user.next(user);
spectator.service.canActivate(null, null);
expect(spyNavigate).toHaveBeenCalled();
});
});
现在当我运行这个覆盖配置不起作用.这是意料之中的,因为在更改配置对象之前已经传递了它.但是如何实现我的目标呢?我试过这个:
Now when I run this overriding the config does not work. This is to be expected, since the config object was already passed on before altering it.But how to achieve my goal?I tried this:
describe('AuthGuard', () => {
let spectator: SpectatorService<AuthGuard>;
const config = {
service: AuthGuard,
imports: [RouterTestingModule, HttpClientTestingModule],
providers: [AppRoutingModule, AuthService, { provide: PLATFORM_ID, useValue: 'server' }],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
};
// some other tests here ....
it('should should navigate to /auth if running on browser and not authenticated', () => {
config.providers = [AppRoutingModule, { provide: PLATFORM_ID, useValue: 'browser' }];
const createService = createServiceFactory(config);
spectator = createService();
const spyNavigate = spyOn(spectator.service['router'], 'navigate').and.callThrough();
const user = new User('bla@bla.com', 'id', 'token', new Date(10000));
spectator.service['authService'].user.next(user);
spectator.service.canActivate(null, null);
expect(spyNavigate).toHaveBeenCalled();
});
});
但是这给了我错误 Error: 'beforeEach' should only be used in 'describe' function
我发现这很令人困惑,因为我没有在本规范中使用 beforeEach.
But that gave me the error Error: 'beforeEach' should only be used in 'describe' function
which I found confusing since I am not using beforeEach in this spec.
我觉得像 Spectator 这样的工具应该有一个简单的方法来做到这一点,它不是那么奇特,对吧?
I feel that some tool like Spectator should probably have an easy way to do this, it is not that exotic, right?
感谢任何帮助!
推荐答案
您可以通过将参数传递给 createService()
来实现:
You can do this by passing arguments to createService()
:
createService({
providers: [...]
});
这篇关于旁观者:覆盖单个测试的提供者(角度通用)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!