【问题标题】:Unit-testing Injector after manually injecting Router (APP_INITIALIZER)手动注入路由器后的单元测试注入器(APP_INITIALIZER)
【发布时间】:2020-05-11 05:43:07
【问题描述】:

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

我尝试用导入中的RouterTestingModule 替换提供程序中的Router,但仍然出现同样的错误。

有什么想法吗?

谢谢!

===

编辑:添加routerStub

编辑 2:分辨率

感谢@Inge Olaisen 的输入,我能够解决错误。答案:

1 - 带有useClass(带承诺)而不是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)))
});

【问题讨论】:

    标签: angular unit-testing dependency-injection karma-jasmine angular-router


    【解决方案1】:

    好吧,你没有提供任何关于你的 routerstub 的信息,或者它是如何设置的,但你需要做的是将返回值模拟为一个 Promise。因为它期望得到一个,但它没有得到任何东西,因此它是未定义的。

    换句话说,.navigate 不会返回 this.router。

    你可以试试:

    class MockRoute {
    navigate(routePath: any[], params: any) {
    return new Promise();
    }}
    

    完全免责声明,我不习惯创建 Promise,我习惯于 observable 的方式,所以你可能需要正确地模拟新的 Promise 部分。

    不过,我建议您使用 TypeMoq。然后你只需使用: 常量路由器 = TypeMock.Mock.ofType(); router.setup(r => r.navigate).returns(()=> new Promise());

    然后你使用 router.object 而不是 routerStub,但它会是: { 提供:路由器,使用工厂:()=> router.object } 代替 {提供:路由器,使用值:路由器存根}

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 2014-09-28
      • 2018-03-31
      • 1970-01-01
      • 2017-10-08
      • 2012-05-20
      相关资源
      最近更新 更多