Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

test - No provider for TranslateService

I'm running some tests using the ng test command and I get the following error message:

NullInjectorError: R3InjectorError(DynamicTestModule)[TranslateService -> TranslateService]: 
  NullInjectorError: No provider for TranslateService!

The test is:

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { TranslateTestingModule } from 'ngx-translate-testing';
import { CoreModule } from './core.module';

const ENGLISH_LANGUAGE = 'en';

describe('AppComponent', () => {

  let fixture: ComponentFixture<AppComponent>;
  let appComponent: AppComponent;

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

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      imports: [
        CoreModule,
        TranslateTestingModule
          .withTranslations(ENGLISH_LANGUAGE, require('assets/i18n/en.json'))
          .withDefaultLanguage(ENGLISH_LANGUAGE)
      ],
    }).compileComponents();
  });

  it('should create the app', async(() => {
    expect(appComponent).toBeTruthy();
  }));

  it('should have as title', async(() => {
    appComponent.ngOnInit();
    fixture.whenStable().then(() => {
      expect(appComponent.testTitle).toEqual('app');
    })
  }));

});

And the component is:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  testTitle?: string;

  constructor(
    private translateService: TranslateService,
    private screenDeviceService: ScreenDeviceService
  ) {}

  public ngOnInit() {
    const subscription: Subscription = this.translateService.get('app.title').subscribe((text: string) => {
      this.afterLanguageResourcesLoaded();
      subscription.unsubscribe();
    });
  }

  private afterLanguageResourcesLoaded(): void {
    this.setAppMetaData();
  }

  private setAppMetaData(): void {
    this.screenDeviceService.setMetaData({
      title: this.translateService.instant('app.title'),
      description: this.translateService.instant('app.description')
    });
    this.testTitle = this.translateService.instant('app.title');
  }

}

I also tried importing the BrowserModule module:

imports: [
  BrowserAnimationsModule,

And I tried adding a TranslateService provider:

providers: [
  TranslateService
]

I finally tried having two member variables for the two services to be injected into the component constructor:

let translateService: TranslateService;
let screenDeviceService: ScreenDeviceService;

and providing them:

providers: [
  TranslateService,
  ScreenDeviceService
]

and getting them:

translateService = TestBed.get(TranslateService);
screenDeviceService = TestBed.get(ScreenDeviceService);

But nothing helped.

I'm under Angular 9.0.4

UPDATE: I ended up using the real translate service instead of the mocked one and had to kill the test runner and type in again the ng test command for my source code to be considered.

like image 719
Stephane Avatar asked May 08 '20 11:05

Stephane


1 Answers

In your test spec.ts file you could add this type of import, with forRoot():

TranslateModule.forRoot()

An example:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        TranslateModule.forRoot(),
        HttpClientTestingModule
      ],
      declarations: [ HomeComponent ],
      schemas: [ NO_ERRORS_SCHEMA ]
    })
    .compileComponents();
  }));

This because you haven't to test the TranslateModule too. This solution works to me.

like image 196
aepifano Avatar answered Sep 20 '22 17:09

aepifano