Angular 7 тестирование с наследованием и глобальным инжектором - PullRequest
0 голосов
/ 25 января 2019

Я начинаю новый проект в Angular 7 и имею базовый компонент для центрирования некоторых моих глобальных переменных и сервисов. Поскольку проект может вырасти довольно большим, я выбрал этот подход, чтобы избежать огромного количества импорта в начале каждого компонента, а также при вызовах super (). Для этого я реализовал подход, описанный здесь , где внешний класс хранит инжектор зависимости, который будет использоваться в базовом компоненте. Как обсуждалось здесь , необходимо было внести изменение, чтобы соответствовать Angular 7 (инжектор должен был быть инициализирован в AppModule). (См. Плункер ниже)

Это прекрасно работает для запуска проекта, проблема возникает, когда я пытаюсь запустить модульные тесты (используя karma-jasmine). Поскольку AppInjector инициализируется в модуле, тестирование не инициализирует его. Затем, поскольку мой базовый компонент пытается вызвать функцию инжектора, происходит сбой.

Если у кого-то есть решение для этого, либо путем изменения структуры теста, либо самого AppInjector, это будет с благодарностью.

Вот плункер со всем задействованным кодом. Примером является глобальный компонент уведомлений, использующий модуль тоста primeng и глобальный сервис уведомлений в базовом компоненте. (Я не смог заставить работать плункер, какая-то ошибка типа MIME, но код там есть)

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

Когда я запускаю тест ng, я получаю следующую ошибку:

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)

1 Ответ

0 голосов
/ 25 января 2019

В тестах вы можете получить инжектор от TestBed.Таким образом, вы можете инициализировать свой AppInjector в beforeEach, как и все остальные вещи.Просто сделайте это до вызова 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;
        });
    }));
...