fro*_*.io 5 typescript angular-routing angular angular-router-guards angular-router
我正在 Angular 15.2.9 中实现一个功能性路由器防护,它检查用户是否登录。如果不是这种情况,防护应该返回 或falsea UrlTree(即重定向到登录页面),具体取决于参数redirectToLogin: boolean。
我正在使用类似于本文中的功能路由防护的工厂函数:
\nexport const isLoggedIn = (redirectToLogin: boolean): CanActivateFn => {\n return (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {\n const isLoggedIn = !!inject(CookieService).check(\'some_cookie\');\n\n if (isLoggedIn) return true;\n if (!isLoggedIn && !redirectToLogin) return false;\n\n const redirectUrl = inject(Router).createUrlTree([\'user\', \'sign_in\'], {\n queryParams: { next: encodeURIComponent(`/${next.url.join(\'/\')}`) },\n queryParamsHandling: \'merge\',\n });\n return redirectUrl;\n };\n};\nRun Code Online (Sandbox Code Playgroud)\n它的工作原理与预期一致,但我无法为其编写规范:
\n let cookieServiceSpy;\n let activatedRouteSnapshot;\n\n beforeEach(() => {\n cookieServiceSpy = jasmine.createSpyObj<CookieService>([\'check\']);\n activatedRouteSnapshot = { url: [], data: {} };\n TestBed.configureTestingModule({\n providers: [\n isLoggedIn,\n { provide: CookieService, useValue: cookieServiceSpy },\n {\n provide: ActivatedRouteSnapshot,\n useValue: activatedRouteSnapshot,\n },\n ],\n });\n });\n\n it(\'should return true when secure_user_id cookie is present and redirectToLogin is false\', () => {\n // given\n cookieServiceSpy.check.and.returnValue(true);\n activatedRouteSnapshot.data.redirectToLogin = false;\n // when\n const result = TestBed.runInInjectionContext(isLoggedIn); // <-- this line is the problem\n // then\n expect(result).toBeTrue();\n });\nRun Code Online (Sandbox Code Playgroud)\n导致打字稿错误:\'(redirectToLogin: boolean) => CanActivateFn\' 类型的参数不可分配给 \'() => CanActivateFn\' 类型的参数。\n目标签名提供的参数太少。预计 1 或更多,但得到 0。
\n我也尝试了其他几种选择:
\nTestBed.runInInjectionContext(isLoggedIn as any)\xe2\x9e\x94无法解析 isLoggedIn 的所有参数:(?)。试运行中TestBed.runInInjectionContext(isLoggedIn(false))\xe2\x9e\x94 \'CanActivateFn\' 类型的参数不可分配给 \'() => boolean | 类型的参数 网址树 | 可观察<布尔值 | 网址树> | 承诺<布尔值 | UrlTree>\'. 目标签名提供的参数太少。预计 2 或更多,但得到 0。TestBed.runInInjectionContext(isLoggedIn(false) as any)\xe2\x9e\x94无法解析 isLoggedIn 的所有参数:(?)。试运行中TestBed.runInInjectionContext(isLoggedIn(false)(activatedRouteSnapshot, null))\xe2\x9e\x94 \ 'boolean | 类型的参数 网址树 | 可观察<布尔值 | 网址树> | 承诺<布尔值 | UrlTree>\' 不可分配给类型为 \'() =>unknown\' 的参数。类型“boolean”不可分配给类型“() =>unknown”。TestBed.runInInjectionContext(isLoggedIn(false)(activatedRouteSnapshot, null) as any);\xe2\x9e\x94inject () 必须从注入上下文调用,例如构造函数、工厂函数、字段初始值设定项或与EnvironmentInjector#runInContext.TestBed.runInInjectionContext(isLoggedIn(false) as any)(activatedRouteSnapshot, null);\xe2\x9e\x94该表达式不可调用。类型“{}”没有调用签名。(TestBed.runInInjectionContext(isLoggedIn(false) as any) as any)(activatedRouteSnapshot, null)\xe2\x9e\x94无法解析 isLoggedIn 的所有参数:(?)。我还尝试省略工厂函数并使用 Route Data 作为参数,如此处所示,但注入ActivatedRouteSnapshot是不可能的,并且ActivatedRoute在嵌套的 Observables 中使用结果......必须有一种更简单的方法。
如何测试路由器防护功能?
\n您观察到的错误是由于两件事造成的:
isLoggedInTestBed.runInInjectionContext,您初始化了注入器,并且注入器尝试将提供者转换为工厂,但由于isLoggedIn未注释且具有 1 个或多个参数(此处只有 1 个)而失败。如果您确实需要注入,CanActivateFn您可以使用{provide: isLoggedIn, useValue: () => { ... },但在我们的例子中,您没有注入该函数,您只是调用它。
因此不需要提供该函数并且调用是直接的:
beforeEach(() => {
cookieServiceSpy = jasmine.createSpyObj<CookieService>(['check']);
activatedRouteSnapshot = { url: [], data: {} };
TestBed.configureTestingModule({
providers: [
{ provide: CookieService, useValue: cookieServiceSpy },
],
});
});
it('should return true when secure_user_id cookie is present and redirectToLogin is false', async () => {
// given
cookieServiceSpy.check.and.returnValue(true);
activatedRouteSnapshot.data.redirectToLogin = false;
// when
const result = TestBed.runInInjectionContext(() => isLoggedIn(true)(activatedRouteSnapshot, undefined)); // Double call to retrieve the result.
// then
expect(result).toBeTrue();
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1158 次 |
| 最近记录: |