手动注入路由器后单元测试注入器 (APP_INITIALIZER)
Unit-testing Injector after manually injecting Router (APP_INITIALIZER)
在 app.module.ts
中,我有以下内容:
{provide: APP_INITIALIZER, useFactory: appServiceFactory, multi: true, deps: [AppService]}
我试图在 AppService
中添加 Router
依赖项,但出现以下错误:
Cannot instantiate cyclic dependency! ApplicationRef...
我将 Injector
添加到我的 AppService
构造函数中,并手动添加 Router
:
private get router() {
return this.injector.get(Router);
}
我这样成功使用了:
this.router.navigate([ routePath ], {queryParams: {type: paramType}})
.then(() => {
return resolve();
});
===
为了测试,我将 Injector
添加到提供程序,并且还添加了 Router
:
let injector: Injector;
const routerStub = {navigate: jasmine.createSpy('navigate')};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
AppService,
...,
Injector,
{provide: Router, useValue: routerStub}
]
});
injector = TestBed.get(Injector);
spyOn(injector, 'get').and.returnValue(routerStub);
});
我收到以下错误:
ERROR LOG: 'Unhandled Promise rejection:', 'Cannot read property 'then' of undefined', '; Zone:', 'ProxyZone', '; Task:', 'jasmine.onComplete', '; Value:', TypeError: Cannot read property 'then' of undefined
TypeError: Cannot read property 'then' of undefined
我尝试将提供程序中的 Router
替换为导入中的 RouterTestingModule
,但仍然出现相同的错误。
有什么想法吗?
谢谢!
===
编辑:已添加 routerStub
编辑 2:分辨率
感谢@Inge Olaisen 的帮助,我得以解决错误。答案:
1 - 使用 useClass
(w/promise)而不是 useValue
的存根路由器
class MockRouter {
navigate(routePath: any[], params: any) {
return new Promise<boolean>(resolve => resolve(true));
}
}
...
{provide: Router, useClass: MockRouter}
...
injector = TestBed.get(Injector);
spyOn(injector, 'get').and.returnValue(routerStub); // Not needed anymore
2 - 使用 RouterTestingModule
let injector: Injector;
let router: Router;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
providers: [
AppService,
...,
Injector,
{provide: Router, useValue: routerStub}
]
});
injector = TestBed.get(Injector);
router = TestBed.get(Router);
spyOn(router, 'navigate').and.returnValue(new Promise<boolean>(resolve => resolve(true)))
});
嗯,你没有提供任何关于你的 routerstub 的信息,或者它是如何设置的,但你需要做的是模拟 return 值作为一个承诺。因为它期望得到一个,但是什么也没有得到,所以它是未定义的。
换句话说,.navigate 不 return this.router。
你可以试试:
class MockRoute {
navigate(routePath: any[], params: any) {
return new Promise();
}}
完全免责声明,我不习惯创建承诺,我习惯了可观察的方式,所以你可能需要正确地模拟新的承诺部分。
不过,我确实建议您使用 TypeMoq。那么你只需使用:
const 路由器 = TypeMock.Mock.ofType();
router.setup(r => r.navigate).returns(()=> new Promise());
然后你使用 router.object 而不是 routerStub,但它会是:
{ provide: Router, useFactory: ()=> router.object }
代替
{provide: Router, useValue: routerStub}
在 app.module.ts
中,我有以下内容:
{provide: APP_INITIALIZER, useFactory: appServiceFactory, multi: true, deps: [AppService]}
我试图在 AppService
中添加 Router
依赖项,但出现以下错误:
Cannot instantiate cyclic dependency! ApplicationRef...
我将 Injector
添加到我的 AppService
构造函数中,并手动添加 Router
:
private get router() {
return this.injector.get(Router);
}
我这样成功使用了:
this.router.navigate([ routePath ], {queryParams: {type: paramType}})
.then(() => {
return resolve();
});
===
为了测试,我将 Injector
添加到提供程序,并且还添加了 Router
:
let injector: Injector;
const routerStub = {navigate: jasmine.createSpy('navigate')};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
AppService,
...,
Injector,
{provide: Router, useValue: routerStub}
]
});
injector = TestBed.get(Injector);
spyOn(injector, 'get').and.returnValue(routerStub);
});
我收到以下错误:
ERROR LOG: 'Unhandled Promise rejection:', 'Cannot read property 'then' of undefined', '; Zone:', 'ProxyZone', '; Task:', 'jasmine.onComplete', '; Value:', TypeError: Cannot read property 'then' of undefined
TypeError: Cannot read property 'then' of undefined
我尝试将提供程序中的 Router
替换为导入中的 RouterTestingModule
,但仍然出现相同的错误。
有什么想法吗?
谢谢!
===
编辑:已添加 routerStub
编辑 2:分辨率
感谢@Inge Olaisen 的帮助,我得以解决错误。答案:
1 - 使用 useClass
(w/promise)而不是 useValue
的存根路由器
class MockRouter {
navigate(routePath: any[], params: any) {
return new Promise<boolean>(resolve => resolve(true));
}
}
...
{provide: Router, useClass: MockRouter}
...
injector = TestBed.get(Injector);
spyOn(injector, 'get').and.returnValue(routerStub); // Not needed anymore
2 - 使用 RouterTestingModule
let injector: Injector;
let router: Router;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
providers: [
AppService,
...,
Injector,
{provide: Router, useValue: routerStub}
]
});
injector = TestBed.get(Injector);
router = TestBed.get(Router);
spyOn(router, 'navigate').and.returnValue(new Promise<boolean>(resolve => resolve(true)))
});
嗯,你没有提供任何关于你的 routerstub 的信息,或者它是如何设置的,但你需要做的是模拟 return 值作为一个承诺。因为它期望得到一个,但是什么也没有得到,所以它是未定义的。
换句话说,.navigate 不 return this.router。
你可以试试:
class MockRoute {
navigate(routePath: any[], params: any) {
return new Promise();
}}
完全免责声明,我不习惯创建承诺,我习惯了可观察的方式,所以你可能需要正确地模拟新的承诺部分。
不过,我确实建议您使用 TypeMoq。那么你只需使用: const 路由器 = TypeMock.Mock.ofType(); router.setup(r => r.navigate).returns(()=> new Promise());
然后你使用 router.object 而不是 routerStub,但它会是: { provide: Router, useFactory: ()=> router.object } 代替 {provide: Router, useValue: routerStub}