9
votes

Angular 9 "Erreur: ce constructeur n'était pas compatible avec l'injection de dépendances."

Cette erreur étrange, que je ne me souviens pas avoir vue avant Ivy, est apparue dans la configuration d'une nouvelle application créée avec la dernière CLI Angular 9. On dirait que ça pourrait être un bug avec Ivy? Toute idée sur la façon de réparer serait grandement appréciée.

Résultat d'erreur du test ng

  "dependencies": {
    "@angular/animations": "~9.0.2",
    "@angular/cdk": "^8.0.0",
    "@angular/common": "~9.0.2",
    "@angular/compiler": "~9.0.2",
    "@angular/core": "~9.0.2",
    "@angular/forms": "~9.0.2",
    "@angular/platform-browser": "~9.0.2",
    "@angular/platform-browser-dynamic": "~9.0.2",
    "@angular/router": "~9.0.2",
    "devextreme": "latest",
    "devextreme-angular": "latest",
    "rxjs": "~6.5.4",
    "tslib": "^1.10.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.3",
    "@angular/cli": "~9.0.3",
    "@angular/compiler-cli": "~9.0.2",
    "@angular/language-service": "~9.0.2",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^5.1.2",
    "devextreme-cli": "latest",
    "devextreme-themebuilder": "latest",
    "husky": "^4.2.3",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~2.1.0",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.2",
    "prettier": "^1.19.1",
    "pretty-quick": "^2.0.1",
    "protractor": "~5.4.3",
    "ts-node": "~8.3.0",
    "tslint": "~5.18.0",
    "tslint-config-prettier": "^1.18.0",
    "typescript": "~3.7.5",
    "webpack-bundle-analyzer": "^3.6.0"
  }

app.component.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';

import { AppComponent } from './app.component';
import { AuthService } from './shared/services';

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent],
      providers: [AuthService, Router],
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

app.component.spec.ts

import { Component, HostBinding } from '@angular/core';
import { AuthService, ScreenService, AppInfoService } from './shared/services';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  @HostBinding('class') get getClass() {
    return Object.keys(this.screen.sizes)
      .filter(cl => this.screen.sizes[cl])
      .join(' ');
  }

  constructor(
    private authService: AuthService,
    private screen: ScreenService,
    public appInfo: AppInfoService,
  ) {}

  isAuthorized() {
    return this.authService.isLoggedIn;
  }
}

dépendances package.json

Error: This constructor was not compatible with Dependency Injection.
    at Module.ɵɵinvalidFactory (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:14150:1)
    at Object.Router_Factory [as factory] (http://localhost:9876/_karma_webpack_/node_modules/@angular/router/__ivy_ngcc__/fesm5/router.js:4404:67)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.hydrate (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:11425:1)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:11247:1)
    at injectInjectorOnly (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:787:1)
    at ɵɵinject (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:792:1)
    at Object.AuthService_Factory [as factory] (ng:///AuthService/ɵfac.js:5:39)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.hydrate (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:11425:1)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:11247:1)
    at NgModuleRef$1.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.NgModuleRef$1.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js:24218:1)

Error: Expected undefined to be truthy.
    at <Jasmine>
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/app/shared/components/header/header.component.spec.ts:25:23)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone.js:396:1)
    at ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:305:1)

REMARQUE: cette erreur est apparue après la correction de NullInjectorError pour AuthService et Router.


2 commentaires

Probablement un @Injectable() manquant sur l'un des services que vous y injectez. Avec ivy, tous les services doivent avoir ce décorateur maintenant, peu importe si le service en question injecte quelque chose dans son constructeur


Cela ne semble pas. Tous les services ont @Injectable() .


3 Réponses :


23
votes

Vous avez défini un Router comme fournisseur dans votre test. Ce n'est pas la manière de procéder.

Vous devez importer le RouterTestingModule dans votre test pour pouvoir y accéder.

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    declarations: [AppComponent],
    providers: [AuthService],
  }).compileComponents();
}));

Je suppose qu'avec ivy et / ou angular 9, ils ont déclaré le providedIn du service du routeur de telle sorte que vous ne pouvez plus le fournir dans un autre module (ce que vous ne devriez jamais faire de toute façon :))


Informations de fond:

En regardant le code source , vous pouvez voir qu'ils injectent le routeur d'une manière spéciale en utilisant une usine. La classe de routeur elle-même n'est qu'une classe normale sans décorateur @Injectable() .


1 commentaires

Merci Monsieur! Très appréciée! J'aurais dû vérifier cela étant donné qu'il n'y a pas de Service à la fin.



6
votes

Une autre source de cette erreur (non liée à la question de l'OP) peut être lorsque vous avez un paramètre de constructeur avec un argument par défaut tel que:

constructor(@Inject('propVal') @Optional() someProp: string) {
    this.someProp = someProp;
}


Vous pouvez le résoudre en faisant ceci à la place:

constructor(someProp: string = 'propVal') {
    this.someProp = someProp;
}


1 commentaires

@Optional m'a aidé à résoudre ce scénario exact ... merci pour le partage!



1
votes

Cette erreur peut également se produire si vous essayez accidentellement d'injecter une interface au lieu d'un service, lol.

example.interface.ts

import { Injectable } from '@angular/core'

@Injectable({
  providedIn: 'root'
})
export class DependentService {
  constructor(
    private example: ExampleInterface // This is the error; should be ExampleService
  ) { }
}

example.service.ts

import { Injectable } from '@angular/core'

@Injectable({
  providedIn: 'root'
})
export class ExampleService {
  constructor() { }
}

depend.service.ts

export interface ExampleInterface {
  id: string
}


0 commentaires