Angular-Karma 単体テストのNullInjectorErrorなどの対応[ionic4]
Angularで単体テストを行う場合、Karmaによるテストを実施する。Serviceクラスのテストは特に問題ないことが多いのだが、PageやComponentのテストはそこでinjectionしているモジュールをTestクラスでもセットしなければいけない。
しかし、モジュールによってこのやり方が様々で、ただimportすれば良いもの、mockをセットする必要があるものなどややこしいので、情報をまとめる。
Contents
providersにセット
以下のようなエラーが出た時。
NullInjectorError: StaticInjectorError(DynamicTestModule)[AppVersion]:
app.module.tsやテスト対象のmodule.tsの"providers"にセットされているものの場合は、TestingModuleでも"providers"でセットすれば大体解決する。
解決策
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ TestPage ], providers: [AppVersion] }) .compileComponents(); }));
RouterTestingModule
以下のエラーが出た時。
NullInjectorError: StaticInjectorError(DynamicTestModule)[Router -> Location]:
解決策
PageClassなどでNavControllerをインジェクションしているときは以下のように対応。
import {RouterTestingModule} from "@angular/router/testing"; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ TestPage ], imports: [ RouterTestingModule ] }) .compileComponents(); }));
TranslateTestingModule
以下のエラーが出た時。
NullInjectorError: StaticInjectorError(DynamicTestModule)[TranslateService]:
解決策
以下のようなMockファイルを自作する。
translate-testing.module
import { Injectable, NgModule, Pipe, PipeTransform } from '@angular/core'; import { TranslateModule, TranslatePipe, TranslateService } from '@ngx-translate/core'; import { Observable, of } from 'rxjs'; const translations: any = {}; @Pipe({ name: 'translate' }) export class TranslatePipeMock implements PipeTransform { public name = 'translate'; public transform(query: string, ...args: any[]): any { return query; } } @Injectable() export class TranslateServiceStub { public get(key: T): Observable { return of(key); } public addLangs(langs: string[]) { } public setDefaultLang(lang: string) { } public getBrowserLang(): string { return 'en'; } public use(lang: string) { } } @NgModule({ declarations: [ TranslatePipeMock ], providers: [ { provide: TranslateService, useClass: TranslateServiceStub }, { provide: TranslatePipe, useClass: TranslatePipeMock }, ], imports: [ TranslateModule.forRoot({}) ], exports: [ TranslatePipeMock, TranslateModule ] }) export class TranslateTestingModule { }
この自作MockをTestingModuleのimportsにセット。
import {TranslateTestingModule} from "@/your-path/translate-testing.module"; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ TestPage ], imports: [ TranslateTestingModule ], }) .compileComponents(); }));
@NgModule.entryComponentsエラー
テスト対象moduleで他のコンポーネントをloadしている場合で、以下のエラーが出た時。
Error: No component factory found for YOURComponent. Did you add it to @NgModule.entryComponents?
解決策
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [YOURComponent], }).overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [YOURComponent] } }) .compileComponents(); }));
ModalControllerエラー
テスト対象moduleでModalControllerをインジェクションしている場合。
NullInjectorError: StaticInjectorError(DynamicTestModule)[TestPage -> ModalController]:
解決策
let modalSpy = jasmine.createSpyObj('Modal', ['present']); let modalCtrlSpy = jasmine.createSpyObj('ModalController', ['create']); modalCtrlSpy.create.and.callFake(function () { return modalSpy; }); beforeEach(async(() => { TestBed.configureTestingModule({ providers: [ { provide: ModalController, useValue: modalCtrlSpy } ] }).compileComponents(); }));
APP_BASE_HREFエラー
Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.
解決策
以下のようにするとエラーを解消できる。
beforeEach(async(() => { TestBed.configureTestingModule({ providers: [ {provide: APP_BASE_HREF, useValue: '/'} ] }).compileComponents(); }));
ディスカッション
コメント一覧
まだ、コメントがありません