Angular:有没有办法在单元测试中模拟 PLATFORM_ID 的值?
Angular: Is there a way to mock the value of PLATFORM_ID in a unit test?
我正在使用 Angular 通用。我有一个行为不同的路由守卫,具体取决于我是 运行 服务器还是浏览器平台。这里是守卫:
export class UniversalShellGuard implements CanActivate {
private isBrowser: boolean;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {
console.log('PLATFORM_ID = ' + platformId);
this.isBrowser = isPlatformBrowser(this.platformId);
}
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
return !this.isBrowser;
}
}
如您所见,守卫正在注射 PLATFORM_ID
并用它来确定他是否 canActivate()
。
现在,我想为守卫编写一个简单的单元测试并执行了以下操作:
describe('UniversalShellGuard', () => {
let guard: UniversalShellGuard;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
UniversalShellGuard,
// Idea: for now I just want to test the behaviour if I would be on the browser, so I would just use a fixed value for PLATFORM_ID
{ provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID },
],
});
guard = TestBed.get(UniversalShellGuard);
});
it('should deny', () => {
expect(guard.canActivate()).toBe(false);
});
});
但它给出了以下错误:
ERROR in ./src/app/universal-shell.guard.spec.ts
Module not found: Error: Can't resolve '@angular/common/src/platform_id' in '/my-app-path/src/app'
@ ./src/app/universal-shell.guard.spec.ts 4:0-70 11:50-69
@ ./src sync \.spec\.ts$
@ ./src/test.ts
我什至尝试了一个简单直接的守卫构造,没有使用 angular TestBed
:
it('should deny', () => {
const guard = new UniversalShellGuard(PLATFORM_BROWSER_ID);
expect(guard.canActivate()).toBe(false);
});
同样的错误。
是否有任何方法可以为 PLATFORM_ID
提供固定值,以便对此类守卫进行正确的单元测试?
值 PLATFORM_BROWSER_ID
不是 public API 的一部分,这就是它从深层路径导入它的原因,这是不允许的。相反,您可以只输入 'browser'
:
{ provide: PLATFORM_ID, useValue: 'browser' },
对于任何其他平台,您可以使用 these 值:
export const PLATFORM_BROWSER_ID = 'browser';
export const PLATFORM_SERVER_ID = 'server';
export const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';
export const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';
另一种测试方法是模拟 isPlatformBrowser
的结果。为此,您应该创建该函数的包装器:
export class UniversalShellGuard implements CanActivate {
...
private isBrowser(): boolean {
return isPlatformBrowser(this.platformId);
}
}
然后,使用 jasmine Spy,您可以模拟 isBrowser()
方法的返回值:
describe('UniversalShellGuard', () => {
let guard: UniversalShellGuard;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
UniversalShellGuard,
{ provide: PLATFORM_ID, useValue: '' },
],
});
guard = TestBed.get(UniversalShellGuard);
});
it('should deny', () => {
spyOn(guard, 'isBrowser').and.returnValue(true);
expect(guard.canActivate()).toBe(false);
});
});
我正在使用 Angular 通用。我有一个行为不同的路由守卫,具体取决于我是 运行 服务器还是浏览器平台。这里是守卫:
export class UniversalShellGuard implements CanActivate {
private isBrowser: boolean;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {
console.log('PLATFORM_ID = ' + platformId);
this.isBrowser = isPlatformBrowser(this.platformId);
}
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
return !this.isBrowser;
}
}
如您所见,守卫正在注射 PLATFORM_ID
并用它来确定他是否 canActivate()
。
现在,我想为守卫编写一个简单的单元测试并执行了以下操作:
describe('UniversalShellGuard', () => {
let guard: UniversalShellGuard;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
UniversalShellGuard,
// Idea: for now I just want to test the behaviour if I would be on the browser, so I would just use a fixed value for PLATFORM_ID
{ provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID },
],
});
guard = TestBed.get(UniversalShellGuard);
});
it('should deny', () => {
expect(guard.canActivate()).toBe(false);
});
});
但它给出了以下错误:
ERROR in ./src/app/universal-shell.guard.spec.ts
Module not found: Error: Can't resolve '@angular/common/src/platform_id' in '/my-app-path/src/app'
@ ./src/app/universal-shell.guard.spec.ts 4:0-70 11:50-69
@ ./src sync \.spec\.ts$
@ ./src/test.ts
我什至尝试了一个简单直接的守卫构造,没有使用 angular TestBed
:
it('should deny', () => {
const guard = new UniversalShellGuard(PLATFORM_BROWSER_ID);
expect(guard.canActivate()).toBe(false);
});
同样的错误。
是否有任何方法可以为 PLATFORM_ID
提供固定值,以便对此类守卫进行正确的单元测试?
值 PLATFORM_BROWSER_ID
不是 public API 的一部分,这就是它从深层路径导入它的原因,这是不允许的。相反,您可以只输入 'browser'
:
{ provide: PLATFORM_ID, useValue: 'browser' },
对于任何其他平台,您可以使用 these 值:
export const PLATFORM_BROWSER_ID = 'browser';
export const PLATFORM_SERVER_ID = 'server';
export const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';
export const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';
另一种测试方法是模拟 isPlatformBrowser
的结果。为此,您应该创建该函数的包装器:
export class UniversalShellGuard implements CanActivate {
...
private isBrowser(): boolean {
return isPlatformBrowser(this.platformId);
}
}
然后,使用 jasmine Spy,您可以模拟 isBrowser()
方法的返回值:
describe('UniversalShellGuard', () => {
let guard: UniversalShellGuard;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
UniversalShellGuard,
{ provide: PLATFORM_ID, useValue: '' },
],
});
guard = TestBed.get(UniversalShellGuard);
});
it('should deny', () => {
spyOn(guard, 'isBrowser').and.returnValue(true);
expect(guard.canActivate()).toBe(false);
});
});