77

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.

Alexander Nied
  • 12,804
  • 4
  • 25
  • 45
Kingamere
  • 9,496
  • 23
  • 71
  • 110
  • 1
    What is the code of the unit test? It matters. – JB Nizet Dec 13 '18 at 20:22
  • Possible duplicate of [Angular 4 Error: No provider for HttpClient](https://stackoverflow.com/questions/46569404/angular-4-error-no-provider-for-httpclient) – Kevin Doyon Dec 13 '18 at 20:25
  • @KevinDoyon No, my question is about failing in regard to unit tests, not otherwise. – Kingamere Dec 13 '18 at 20:33
  • 4
    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 stuff – Kevin Doyon Dec 13 '18 at 20:39
  • @KevinDoyon You're right, thank you, I just needed to import `HttpClientTestingModule`. – Kingamere Dec 13 '18 at 20:44

3 Answers3

139
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();
       });

    });
Alexander Nied
  • 12,804
  • 4
  • 25
  • 45
The Dead Man
  • 6,258
  • 28
  • 111
  • 193
  • 15
    Thanks, I just needed to add `HttpClientTestingModule` to the `imports` array in the `configureTestingModule` method. – Kingamere Dec 13 '18 at 20:43
  • Yes, I wanted to just post that but I said let make it full , am happy it helped – The Dead Man Dec 13 '18 at 21:04
  • working for me, I was aspecting to add the module in the main test instead it must be added in the test of the service – Salvatore Pannozzo Capodiferro Apr 29 '19 at 13:06
  • 3
    This helped but import {HttpClientModule} from '@angular/common/http'; is not necessary since the test class does not actually use it. – iowatiger08 Sep 11 '19 at 15:21
  • 1
    Thanks! This worked for me in Angular 9. import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; beforeEach(() => TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [myService] })); – Hassan Raza Jun 07 '20 at 08:03
  • I spent most of my time trying to figure out how to create Jasmine Spy HttpClient object until I found this solution. Thanks. – Tinashe Dec 19 '20 at 14:05
  • 6
    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. – bob Apr 09 '21 at 14:36
  • In this example, nobody pointed whats the use of HttpTestingController import ? – OmGanesh Sep 08 '22 at 03:40
1
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]
  }));
});
Sanka Sanjeewa
  • 1,993
  • 14
  • 16
0

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

Derviş Kayımbaşıoğlu
  • 28,492
  • 4
  • 50
  • 72