Angular 5 и lerna NullInjectorError: Нет поставщика для InjectionToken

Мой вариант использования следующий:

  • У меня есть 2 библиотеки angular5.
  • Обе библиотеки клонированы из следующего проекта: https://github.com/robisim74/angular-library-starter
  • У меня есть монорепо, которым управляет Лерна
  • дочерняя библиотека имеет очень простую директиву, которую должна использовать родительская библиотека.

код для детской библиотеки

import { NgModule } from '@angular/core';
import {CommonModule} from "@angular/common";

@NgModule({
    imports: [CommonModule],
    declarations: [
        SampleDirective
    ],
    exports: [
        SampleDirective
    ]
})
export class ChildModule { }

Код для директивы в дочерней библиотеке

import {Directive, PLATFORM_ID, Inject} from '@angular/core';

@Directive({
    selector: '.sample'
})
export class SampleDirective {
    constructor(@Inject(PLATFORM_ID) private _element: Object) {

    }
}

В родительском я установил дочерний модуль, и я делаю следующий простой модульный тест

import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {ChildModule} from "@nz/child-lib";

@Component({
    selector: 'nz-host',
    template: `
        <div class="sample"></div>
    `
})
export class TestWrapperComponent{}


describe('injection problem', () => {
    let testFixture: ComponentFixture<TestWrapperComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [TestWrapperComponent],
            imports: [ChildModule]                
        });
    }));

    beforeEach(async(() => {
        testFixture = TestBed.createComponent(TestWrapperComponent);
        testFixture.detectChanges();
    }));

    it('test', () => {
        expect(true).toBe(true);
    });
});

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

StaticInjectorError [Идентификатор платформы InjectionToken]: NullInjectorError: Нет поставщика для идентификатора платформы InjectionToken! Ошибка: StaticInjectorError[ID платформы InjectionToken]: в _NullInjector.get (веб-пакет:///node_modules/@angular/core/esm5/core.js:923:0 <- spec.bundle.js: 3517: 19) в resolToken (webpack: ///node_modules/@angular/core/esm5/core.js: 1211: 0 <- spec.bundle.js: 3805: 24) в tryResolveToken (webpack: /// node_modules / @ angular / core / esm5 / core.js: 1153: 0 <- spec.bundle.js: 3747: 16) в StaticInjector.get (веб-пакет: ///node_modules/@angular/core/esm5/core.js: 1024: 0 <- spec.bundle.js: 3618: 20) в resolToken (веб-пакет: ///node_modules/@angular/core/esm5/core.js: 1211: 0 <- spec.bundle.js: 3805: 24) в tryResolveToken (веб-пакет: // /node_modules/@angular/core/esm5/core.js:1153:0 <- spec.bundle.js: 3747: 16) в StaticInjector.get (веб-пакет: /// node_modules / @ angular / core / core / esm5 / core. js: 1024: 0 <- spec.bundle.js: 3618: 20) at resolNgModuleDep (веб-пакет: ///node_modules/@angular/core/esm5/core.js: 10584: 0 <- spec.bundle.js: 13178: 25) в NgModuleRef_.get (веб-пакет: ///node_modules/@angular/core/esm5/core.js: 11805: 0 <- spec.bundle.js: 14399: 16) at resolDep (веб-пакет: ///node_modules/@angular/core/esm5/core.js: 12301: 0 <- spec.bundle.js: 14895: 45)

Мой package.json это:

"dependencies": {
    "tslib": "^1.7.1"
},
"peerDependencies": {
    "@angular/common": ">= 5.0.0",
    "@angular/core": ">= 5.0.0"
},
"devDependencies": {
    "@angular/animations": "5.0.0",
    "@angular/common": "5.0.0",
    "@angular/compiler": "5.0.0",
    "@angular/compiler-cli": "5.0.0",
    "@angular/core": "5.0.0",
    "@angular/platform-browser": "5.0.0",
    "@angular/platform-browser-dynamic": "5.0.0",
    "@angular/platform-server": "5.0.0",
    "@compodoc/compodoc": "1.0.3",
    "@nz/child-lib": "^0.0.1",
    "@types/jasmine": "2.6.2",
    "@types/node": "8.0.47",
    "chalk": "2.3.0",
    "codelyzer": "4.0.2",
    "core-js": "2.5.1",
    "istanbul-instrumenter-loader": "3.0.0",
    "jasmine-core": "2.8.0",
    "karma": "1.7.1",
    "karma-chrome-launcher": "2.2.0",
    "karma-coverage-istanbul-reporter": "1.3.0",
    "karma-jasmine": "1.1.0",
    "karma-sourcemap-loader": "0.3.7",
    "karma-spec-reporter": "0.0.31",
    "karma-webpack": "2.0.5",
    "reflect-metadata": "0.1.10",
    "rollup": "0.50.0",
    "rollup-plugin-license": "0.5.0",
    "rollup-plugin-node-resolve": "3.0.0",
    "rollup-plugin-sourcemaps": "0.4.2",
    "rxjs": "5.5.2",
    "shelljs": "0.7.8",
    "source-map-loader": "0.2.3",
    "ts-loader": "3.1.1",
    "tslint": "5.8.0",
    "tslint-angular": "1.0.0",
    "typescript": "2.4.2",
    "uglify-js": "3.1.6",
    "webpack": "3.8.1",
    "zone.js": "0.8.18"
}

Даже при издевательстве над PLATFORM_ID с помощью следующего кода

{provide: PLATFORM_ID, useValue: 'browser'}

Ошибка все еще там.

пакеты как символические ссылки

У меня есть новая теория, почему это происходит с моей стороны. Я думаю, так как я использую lerna для управления своими пакетами и зависимостями пакетов. И так как я добавил дочерний модуль в модуль хоста через lerna, то lerna создает символическую ссылку дочернего модуля в модулях узла хоста. Итак, моя теория состоит в том, что DI не может определить, что ему нужно вводить, когда библиотека, которую мы используем, является символической ссылкой. Попытка выяснить, как запустить тесты с помощью --preserve-symlinks

большое спасибо

2 ответа

Таким образом, проблема была действительно символическими ссылками. при использовании символических ссылок в ваших node_modules или использовании инструмента управления пакетами, такого как lerna (который связывает внутренние пакеты с помощью symlink). Чем Angular не будет знать, как правильно вводить предметы.

Для меня решение было до запуска тестов, чтобы удалить символические ссылки, установить пакеты с бумажной копией и затем запустить тесты.

Я столкнулся с той же проблемой в мультимодульном проекте Angular 6 и в Lerna.

Во-первых, есть опция под названием preserveSymLinks установить в true в угловом конфигурационном файле (angular.json в угловых 6).

После этого я смог связать модуль со своим проектом со ссылкой на символику, но не со ссылкой на Лерну. Я не знаю почему, но я должен сделать это с помощью команды mklink в среде Windows.

Другие вопросы по тегам