Angular 6 - NullInjectorError: No provider for HttpClient in unit tests
Asked Answered
P

3

85

I am importing and using HttpClient in a service as follows:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
    providedIn: 'root',
})
export class MyService {
    constructor(private http: HttpClient) { }

    getData() {
        return this.http.get("url...");
    }
}

However, when I run ng test for my unit tests, and when those tests use the service, I am getting the error:

Error: StaticInjectorError(DynamicTestModule)[HttpClient]: 
  StaticInjectorError(Platform: core)[HttpClient]: 
    NullInjectorError: No provider for HttpClient!

The Angular 6 documentation on HTTP just says to do what I did above.

Plucky answered 13/12, 2018 at 20:13 Comment(6)
What is the code of the unit test? It matters.Witha
Possible duplicate of Angular 4 Error: No provider for HttpClientPresumably
@KevinDoyon No, my question is about failing in regard to unit tests, not otherwise.Plucky
And that's exactly what that duplicate is about :) You're likely not importing HttpClientModule into your test. Your tests create their own modules. If you don't import HttpClientModule (or HttpClientTestingModule) there, HttpClient won't work because Angular doesn't know about it. It doesn't matter that you added HttpClientModule to, say, AppModule. It needs to be in TestBed.configureTestingModule. Could also import a SharedModule if you have one, as long as HttpClientModule is in the exports.But test will be slower because the SharedModule would contain unneeded stuffPresumably
@KevinDoyon You're right, thank you, I just needed to import HttpClientTestingModule.Plucky
I imported HttpClientTestingModule but it is not working. Still can't find HttpClient...Inseparable
E
151
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import {HttpClientModule} from '@angular/common/http';
import { myService } from './myservice';


describe('myService', () => {

      beforeEach(() => TestBed.configureTestingModule({
        imports: [HttpClientTestingModule], 
        providers: [myService]
      }));

       it('should be created', () => {
        const service: myService = TestBed.get(myService);
        expect(service).toBeTruthy();
       });

       it('should have getData function', () => {
        const service: myService = TestBed.get(myService);
        expect(service.getData).toBeTruthy();
       });

    });
Erumpent answered 13/12, 2018 at 20:20 Comment(9)
Thanks, I just needed to add HttpClientTestingModule to the imports array in the configureTestingModule method.Plucky
Yes, I wanted to just post that but I said let make it full , am happy it helpedErumpent
working for me, I was aspecting to add the module in the main test instead it must be added in the test of the serviceSourwood
This helped but import {HttpClientModule} from '@angular/common/http'; is not necessary since the test class does not actually use it.Sidky
Thanks! This worked for me in Angular 9. import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; beforeEach(() => TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [myService] }));Lunar
I spent most of my time trying to figure out how to create Jasmine Spy HttpClient object until I found this solution. Thanks.Shoebill
A description of what the solution adds--why it works, would be helpful. Without words, I'm forced to do a visual diff between OP's post and this answer.Arthro
In this example, nobody pointed whats the use of HttpTestingController import ?Myrwyn
I imported HttpClientTestingModule like this but it is not working. Still can't find HttpClient..Inseparable
Y
2
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { myService } from './myservice';

describe('HeaderService', () => {
  beforeEach(() => TestBed.configureTestingModule({
    imports: [ HttpClientTestingModule ],
    providers: [myService]
  }));
});
Yap answered 7/5, 2020 at 13:4 Comment(0)
M
-1

you should add HttpClient into imports of your module where your component is declared

@NgModule({
  declarations: [
    MyComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule
  ],
  providers: []
})
export class AppModule { }

UPDATE:

import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; must tbe included for unit testing

OPs question does not follow unit testing guidelines. HttpClientTestingModule must be imported in beforeEach

  beforeEach(() => TestBed.configureTestingModule({
    imports: [HttpClientTestingModule], 
    providers: [dataService]  
  }));

Basically, HttpClientTestingModule is injected in dataService for unit testing purposes that prevents StaticInjectorError

Maidservant answered 13/12, 2018 at 20:22 Comment(1)
The user asks for unit testing... not using it in a serviceBakehouse

© 2022 - 2024 — McMap. All rights reserved.