使用继承和全局注入(inject)器进行 Angular 7 测试

标签 angular dependency-injection frontend karma-jasmine angular7

我正在 Angular 7 中启动一个新项目,并有一个基础组件来集中我的一些全局变量和服务。由于项目可能变得相当大,我选择这种方法是为了避免在每个组件的开头以及 super() 调用时进行大量导入。

为此,我实现了描述的方法 here ,其中外部类存储要在基本组件中使用的依赖项注入(inject)器。正如所讨论的here ,必须进行修改以符合 Angular 7(注入(inject)器必须在 AppModule 处初始化)。 (参见下面的 plunker)

这对于运行项目来说效果很好,当我尝试运行单元测试(使用 karma-jasmine)时,问题就出现了。由于 AppInjector 是在模块中初始化的,因此测试运行不会对其进行初始化。然后,由于我的基本组件尝试调用注入(inject)器的函数,因此它中断了。

如果有人对此有任何解决方案,无论是通过修改测试结构还是 AppInjector 本身,我们将不胜感激。

这是一个包含所有涉及代码的插件。该示例是使用 primeng toast 模块的全局通知组件和基础组件中的全局通知服务。 (我无法让 plunker 正常工作,某种 MIME 类型错误,但代码都在那里)

https://next.plnkr.co/edit/7v5nB8cORWsnpPAL?preview

当我运行 ng test 时,这是我得到的错误:

Chrome 71.0.3578 (Windows 10.0.0) AppComponent should create the app FAILED
        TypeError: Cannot read property 'get' of undefined
            at NotificationsComponent.BaseComponent (http://localhost:9876/src/app/components/base.component.ts?:22:50)
            at new NotificationsComponent (http://localhost:9876/src/app/components/utils/notifications/notifications.component.ts?:17:13)
            at createClass (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:20716:1)
            at createDirectiveInstance (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:20595:1)
            at createViewNodes (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:21821:1)
            at callViewAction (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:22137:1)
            at execComponentViewsAction (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:22056:1)
            at createViewNodes (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:21849:1)
            at createRootView (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:21735:1)
            at callWithDebugContext (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:22767:1)
        Error: Uncaught (in promise): TypeError: Cannot read property 'get' of undefined
            at resolvePromise (http://localhost:9876/node_modules/zone.js/dist/zone.js?:831:1)
            at http://localhost:9876/node_modules/zone.js/dist/zone.js?:896:1
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:9876/node_modules/zone.js/dist/zone.js?:423:1)
            at AsyncTestZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.AsyncTestZoneSpec.onInvokeTask (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:698:1)
            at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvokeTask (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:317:1)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:9876/node_modules/zone.js/dist/zone.js?:422:1)
            at Zone../node_modules/zone.js/dist/zone.js.Zone.runTask (http://localhost:9876/node_modules/zone.js/dist/zone.js?:195:1)
            at drainMicroTaskQueue (http://localhost:9876/node_modules/zone.js/dist/zone.js?:601:1)
        Expected undefined to be truthy.
            at UserContext.<anonymous> (http://localhost:9876/src/app/app.component.spec.ts?:35:21)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:391:1)
            at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:289:1)

最佳答案

在测试中,您可以从TestBed获取注入(inject)器。因此,您可以像其他所有事情一样在 beforeEach 中初始化您的 AppInjector。只需在 createComponent 调用之前执行此操作即可准备就绪。

以下是 Plunker 示例中更改后的代码:

beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [
                RouterTestingModule,
                ToastModule
            ],
            declarations: [
                AppComponent,
                NotificationsComponent
            ]
        }).compileComponents().then(() => {
            AppInjector.setInjector(TestBed.get(Injector));
            fixture = TestBed.createComponent(AppComponent);
            app = fixture.debugElement.componentInstance;
        });
    }));

关于使用继承和全局注入(inject)器进行 Angular 7 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54355903/

相关文章:

javascript - 如何将链接添加到 "Title"或 "image"

javascript - 如何将数据从 Vue 实例传递到嵌套组件

html - 更改选择选项时获取当前值 - Angular2

node.js - 保持 sitemap.xml 更新的最佳方法是什么

Angular queryParamMap 为空,然后填充

Haskell:如何测试使用 wreq 的 Spock 应用程序?

ios - 如何在 Storyboard管理的 UIViewControllers 中依赖注入(inject)?

angular - @angular/common/http/testing TestRequest.flush 一个 boolean 值

unit-testing - 使用数据库的 Web 应用程序中的单元测试

html - 不拉伸(stretch)不同尺寸图片的 Flexbox 画廊布局