I get NullInjectorError: No provider for HttpClient when i run my test.
Using Angular 8 with Karma. I followed examples and am new to Karma. So not sure why this is happening. Why?
Most of what i read says to include the httpclienttesting module. But that does not seem to make a difference.
My getHelpfulLinks component-
import { Component, OnInit } from '@angular/core';
import { TkDataService } from '../tk-services/tk-data/tk-data.service';
@Component({
selector: 'app-tk-helpful-links',
templateUrl: './tk-helpful-links.component.html',
styleUrls: ['./tk-helpful-links.component.scss']
})
export class HelpfulLinksComponent implements OnInit {
public res: {};
getHelpfulLinks(): any {
return this.dataSvc.get('gethelpfulLinks', {})
.subscribe(res => {
this.res = res;
});
}
constructor(
private dataSvc: TkDataService
) {
}
ngOnInit() {
this.getHelpfulLinks();
}
}
}
And my .spec file-
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { HelpfulLinksComponent } from './tk-helpful-links.component';
import { TkDataService } from '../tk-services/tk-data/tk-data.service';
import { HttpClient} from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import {HttpClientModule} from '@angular/common/http';
describe('HelpfulLinksComponent', async() => {
let component: HelpfulLinksComponent;
let http: HttpClient;
let mockTkDataService = new TkDataService(http);
let httpTestingController: HttpTestingController;
let fixture;
beforeEach(async () => {
fixture = TestBed.createComponent(HelpfulLinksComponent);
component = fixture.componentInstance;
fixture.detectChanges();
TestBed.configureTestingModule({
declarations: [ HelpfulLinksComponent ],
imports: [ HttpClientTestingModule ],
})
.overrideComponent(HelpfulLinksComponent, {
set: {
providers: [
{ provide: TkDataService, useValue: mockTkDataService }
]
}
})
.compileComponents();
httpTestingController = TestBed.get(HttpTestingController);
component = TestBed.get(mockTkDataService);
afterEach(() => {
httpTestingController.verify();
});
});
it('HelpfulLinksComponent should be created', () => {
expect(component).toBeTruthy();
});
});
My TKDataService file (partial)-
export class TkDataService {
constructor(
private http: HttpClient
) {
}
get(route: string, data: any, responseType?): Observable<any[]>{
const observe = responseType === 'blob' ? 'response' : 'body';
let requestHeaders = new HttpHeaders();
requestHeaders = requestHeaders.set('Authorization', localStorage.getItem('bearerToken'));
// tslint:disable-next-line: max-line-length
return this.http.get<any[]>(environment.baseAPIUrl + route,
{withCredentials: false, headers: requestHeaders, responseType, observe: observe as 'body'} );
}
}
Short Answer:
You are passing a null httpClient
to mockTkDataService
in these line:
let http: HttpClient;
let mockTkDataService = new TkDataService(http);
What you should do:
You don't need to mock TkDataService
at all.
The HttpClientTestingModule
will resolve the httpClient
inside it.
Just add the original TkDataService
to the providers array in the test bed configuration like this:
TestBed.configureTestingModule({
declarations: [ HelpfulLinksComponent ],
imports: [ HttpClientTestingModule ],
providers: [ TkDataService ]
})
and use it later like this:
const tkDataService = getTestBed().get(TkDataService)
httpService.get<any>(dummyUrl, dummyTelemetryAction).subscribe(
(response: HttpResponse<any>) => {
expect(response).toBeTruthy();
}
const req1 = httpMock.expectOne(dummyUrl);
req1.flush(null, { status: 200, statusText: 'ok' });