Search code examples
angularunit-testingkarma-jasmineprimengkarma-webpack

Angular testing with primeng : NullInjectorError: StaticInjectorError(DynamicTestModule)[ButtonDirective -> ElementRef


I am trying to test my angular 8 app using primeng but karma displays following error :

NullInjectorError: StaticInjectorError(DynamicTestModule)[ButtonDirective -> ElementRef]: 

 StaticInjectorError(Platform: core)[ButtonDirective -> ElementRef]: 

      NullInjectorError: No provider for ElementRef!

I think it is cause of primeng button component, indeed on its github (primeng/src/app/components/button/button.ts) we got that :

export class ButtonDirective implements AfterViewInit, OnDestroy {

    @Input() iconPos: 'left' | 'right' = 'left';

    @Input() cornerStyleClass: string = 'ui-corner-all';

    public _label: string;

    public _icon: string;

    public initialized: boolean;

    constructor(public el: ElementRef) {}

I tried lots of things but nothing worked :'(

I tried :

  • to mock Element Ref by using

    • { provide: ElementRef, useClass: MockElementRef },
    • { provide: ElementRef, useValue: MockElementRef },
  • to add angular in path of tsconfig.json
  • to add "build": { "preserveSymlinks": true } in angular.json

Here is my app.component.spec.ts :

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import {BrowserModule} from "@angular/platform-browser";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";

// Import PrimeNG modules
import {
 /**
    PRIMENG IMPORTS
 **/
 ButtonModule
} from "primeng/primeng";

import { } from 'jasmine'
import { ElementRef } from '@angular/core';

export class MockElementRef extends ElementRef {
  constructor() { super(null); }
  // nativeElement = {};
}

describe('AppComponent', () => {

  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let elRef: ElementRef;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        /**
            LOTS OF MODULES
        **/
        ButtonModule,
      ],
      declarations: [        
        /**
            LOTS OF COMPONENTS
        **/
      ],
      providers: [
        /**
            LOTS OF SERVICES
        **/
        { provide: ElementRef, useClass: MockElementRef },
        // { provide: ElementRef, useValue: MockElementRef },
        { provide: APP_BASE_HREF, useValue: '/' },
        { provide: HTTP_INTERCEPTORS, useClass: HttpClientInterceptor, multi: true },
        { provide: HttpService, useFactory: httpClientCreator, deps: [HttpClient] }
      ]
    }).compileComponents();
    // elRef = TestBed.get(MockElementRef);
  }));

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

  it('should create', () => {
    const app = fixture.debugElement.componentInstance;    
    expect(app).toBeTruthy()
  });
});

Help me pleeeeeeeeeease !!! :'(

*EDIT : *

app.module.ts :

// Import PrimeNG modules
import {
  CalendarModule,
  CheckboxModule,
  ContextMenuModule,
  DialogModule,
  DropdownModule,
  GrowlModule,
  InputTextareaModule,
  PaginatorModule,
  PanelModule, SpinnerModule,
  TabViewModule, ToolbarModule, TooltipModule, KeyFilterModule, ButtonModule
} from "primeng/primeng";
import {TableModule} from "primeng/table";

    /**
       LOTS OF IMPORTS
    **/

// Enable production mode
enableProdMode();

@NgModule({
  imports: [
    /**
       LOTS OF MODULES
    **/
  ],
  declarations: [
    AppComponent,
    /**
       LOTS OF COMPONENTS
    **/
  ],
  bootstrap: [
    AppComponent
  ],
  providers: [
    /**
       LOTS OF SERVICES
    **/
    { provide: APP_BASE_HREF, useValue: '/' },
    { provide: HTTP_INTERCEPTORS, useClass: HttpClientInterceptor, multi: true },
    { provide: HttpService, useFactory: httpClientCreator, deps: [HttpClient] }
  ]
})

export class AppModule {
}

* SOLVED : *

By adding "preserveSymlinks": true in angular.json in "test" section instead of "build" section worked... pretty stupid from me


Solution

  • SOLVED

    My angular.json's test section (added "preserveSymlinks": true):

    "test": {
              "builder": "@angular-devkit/build-angular:karma",
              "options": {
                "main": "src/app/modules/dvy-report/dvy-crud/test.ts",
                "karmaConfig": "./karma.conf.js",
                "polyfills": "src/app/modules/dvy-report/dvy-crud/polyfills.ts",
                "tsConfig": "src/app/modules/dvy-report/dvy-crud/tsconfig.spec.json",
                "scripts": [],
                "styles": [
                  "src/styles.css",
                  "src/sass/primeicons/primeicons.css",
                  "src/sass/font-awesome/font-awesome.css",
                  "src/sass/style.scss",
                  "node_modules/primeng/resources/primeng.css",
                  "src/app/modules/dvy-report/dvy-crud/app.component.css"
                ],
                "assets": [
                  "src/favicon.ico"
                ],
                "preserveSymlinks": true
              }
    }