Andreas
Andreas

Reputation: 27

Angular unit tests for services that uses TranslateService

How do I have to use the TranslateService in unit tests of a service? TranslateService is used in the service class in that way:

export class ErrorControllerService {
    constructor(public translate: TranslateService) {
    }
    ...
}

And I tried to configure the TestingModule TestBed in that way:

import { MyService } from './myservice';
import { TestBed } from '@angular/core/testing';

describe('MyService', () => {
  let myService:MyService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ ],
      imports: [
                TranslateModule.forRoot({
                    loader: {
                        provide: TranslateLoader,
                        useFactory: HttpLoaderFactory,
                        deps: [HttpClient]
                    }
                    }),
      ],
      providers: [ MyService, TranslateService ],
    });
    let myService = TestBed.get(MyService);
  });

  it('should be created', () => {
    expect(myService).toBeDefined();
  });
});

During running of npm test I get this message

NullInjectorError: StaticInjectorError(DynamicTestModule)[TranslateService]: 
  StaticInjectorError(Platform: core)[TranslateService]: 
    NullInjectorError: No provider for TranslateService!
error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ Function ] })
    at <Jasmine>
    at NullInjector.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:778:1)
    at resolveToken (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:2564:1)
    at tryResolveToken (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:2490:1)
    at StaticInjector.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:2353:1)
    at resolveToken (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:2564:1)
    at tryResolveToken (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:2490:1)
    at StaticInjector.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:2353:1)
    at resolveNgModuleDep (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:26403:1)
    at NgModuleRef_.get (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:27491:1)
    at injectInjectorOnly (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:657:1)

Any idea, what I do wrong? My research showed me just examples with a component, but not with a service.

Upvotes: 0

Views: 8081

Answers (1)

maury844
maury844

Reputation: 1250

I think I took this from another answer here on SO but I'm unable to find it, so...

The solution is to build your TranslateTestingModule

I have mocks for the pipe, and the different functions of the service this has worked wonders for me so far.

import { Injectable, NgModule, Pipe, PipeTransform } from '@angular/core';
import {
  TranslateLoader,
  TranslateModule,
  TranslatePipe,
  TranslateService
} from '@ngx-translate/core';

import { Observable, of } from 'rxjs';

const translations: any = {};

class FakeLoader implements TranslateLoader {
  getTranslation(lang: string): Observable<any> {
    return of(translations);
  }
}

@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<T>(key: T): Observable<T> {
    return of(key);
  }

  public getBrowserLang() {
    return 'es';
  }

  public setDefaultLang(language) {}

  public get currentLang() {
    return 'en';
  }

  public instant(key) {
    return 'value';
  }

  public use(lang) {}
}

@NgModule({
  declarations: [TranslatePipeMock],
  providers: [
    { provide: TranslateService, useClass: TranslateServiceStub },
    { provide: TranslatePipe, useClass: TranslatePipeMock }
  ],
  imports: [
    TranslateModule.forRoot({
      loader: { provide: TranslateLoader, useClass: FakeLoader }
    })
  ],
  exports: [TranslatePipeMock, TranslateModule]
})
export class TranslateTestingModule {}

And then you just add it to the imports section of your testing module

Upvotes: 4

Related Questions