1

I am trying to do unit testing in angular 6 , when I run `ng test'

I get the following error

Error: StaticInjectorError(DynamicTestModule)[HttpClient]:
          StaticInjectorError(Platform: core)[HttpClient]:
            NullInjectorError: No provider for HttpClient!
            at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:691:1)
            at resolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:928:1)
            at tryResolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:872:1)
            at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:769:1)
            at resolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:928:1)
            at tryResolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:872:1)
            at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:769:1)
            at resolveNgModuleDep (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:17435:1)
            at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:18124:1)
            at inject (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:1023:1)
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 2 of 12 (2 FAILED) (0 secs / 0.119 secs)
Chrome 69.0.3497 (Windows 10 0.0.0) UserService should have add function FAILED
        Error: StaticInjectorError(DynamicTestModule)[HttpClient]:
          StaticInjectorError(Platform: core)[HttpClient]:
            NullInjectorError: No provider for HttpClient!
            at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:691:1)
            at resolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:928:1)
            at tryResolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:872:1)
            at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:769:1)
            at resolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:928:1)
            at tryResolveToken (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:872:1)
            at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:769:1)
            at resolveNgModuleDep (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:17435:1)
            at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (http://localhost:9876/node_modules/@angular/core/fesm5/core.js?:18124:1)
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 2 of 12 (2 FAILED) (skipped 10) ERROR (0.094 secs / 0.119 secs)

Here is service spec ts file

 import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import {HttpClientModule} from '@angular/common/http';
import { UserService } from './user.service';

TestBed.configureTestingModule({
    imports: [HttpClientTestingModule, HttpClientModule],
    providers: [UserService]
});

fdescribe('UserService', () => {
  beforeEach(() => TestBed.configureTestingModule({}));

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

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

});

Her is usersevice ts file

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {Status } from '../model/statuses.model';
import { Comment } from '../model/comments.model';
import { User } from '../model/user.model';
import { Headers, Http, Response } from '@angular/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Observable, of, throwError } from 'rxjs';
import { HttpHeaders, HttpErrorResponse } from '@angular/common/http';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable({
  providedIn: 'root'
})
export class UserService {
  status: Status[];
  constructor(private http: HttpClient) { }
  statusUrl = 'http://localhost:3000/statuses';
  commentsUrl = 'http://localhost:3000/comment';
  usersUrl = 'http://localhost:3000/users';

  private extractData(res: Response) {
    // tslint:disable-next-line:prefer-const
    let body = res;
    return body || {};
  }

 // get all users
  getUsers(): Observable<any> {
    return this.http.get(this.usersUrl).pipe(
      map(this.extractData),
      catchError(this.handleError));
    }

  // get users by ID
  getUserById(id: number) {
    return this.http.get<User>(this.usersUrl + '/' + id);
  }

  // get all statuses
  getStatuses(): Observable<any> {
    return this.http.get(this.statusUrl).pipe(
      map(this.extractData),
      catchError(this.handleError));
    }

  // add comments
  addComments(comments: Comment) {
    comments.localTime = new Date();
    return this.http.post(this.commentsUrl, comments);
  }

  // get comments
  getComments(id: number): Observable<any> {
    return this.http.get(this.commentsUrl).pipe(
      map(this.extractData),
      catchError(this.handleError));
  }
  // upadet user status
  updateStatus(status: Status) {
  return this.http.put(this.statusUrl + '/' + status.id, status);
  }

  // add user status
  addStatus(status: Status) {
    return this.http.put(this.statusUrl, status);
   }
   // Errors Handler
  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
    // return an observable with a user-facing error message
    return throwError('Something bad happened; please try again later.');
  }

}

I tried different solution from stack oveflow but nothing is working , I tried even this solution here unit test errors angular 5

But unfortunatelly nothing works in angular 6

What am I doing wrong, any help will be apreciated????

The Dead Man
  • 6,258
  • 28
  • 111
  • 193
  • 1
    I believed that you issue relies upon the TestBed definition you'are defining the Testbed on before each test and leave it empty – Jorge Oct 30 '18 at 14:55
  • The `TestBed` configured inside the `describe` scope is called with an empty object literal. Copy the object literal from the initial `TestBed` setup into the second one. – The Head Rush Oct 30 '18 at 14:56
  • @Jorge can you show me how to do it correctly am just dumies here in unit test this is my first unit test though lol :P – The Dead Man Oct 30 '18 at 15:00

1 Answers1

4

I believed that you issue relies upon the TestBed definition you'are doing this twice, potentially this is the issue:

 //first testbed definition, move this into the beforeEach
TestBed.configureTestingModule({
  imports: [HttpClientTestingModule, HttpClientModule],
  providers: [UserService]
});

describe('UserService', () => {
  beforeEach(() => TestBed.configureTestingModule({})); <- second one, cleanning the module definition before each test

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

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

});

It should look like this:

describe('UserService', () => {

  beforeEach(() => TestBed.configureTestingModule({
    imports: [HttpClientTestingModule], // <- notice that I remove the HttpClientModule
    providers: [UserService]
  }));

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

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

});
Jorge
  • 17,896
  • 19
  • 80
  • 126
  • let me check I will be back soon – The Dead Man Oct 30 '18 at 15:07
  • Tested with your solution karma retuns the same error : `Error: StaticInjectorError(DynamicTestModule)[HttpClient]: StaticInjectorError(Platform: core)[HttpClient]: NullInjectorError: No provider for HttpClient!`bI even forced to test only this function by adding f to subscribe `fsubscribe` – The Dead Man Oct 30 '18 at 15:13
  • One more thing that I notice remove the HttpClient module, leave only the HttpClientTestingModule, I'll update the example – Jorge Oct 30 '18 at 15:14
  • @user9964622 Leave only that `TestBed.configureTestingModule` section that goes in beforeEach but with proper imports – yurzui Oct 30 '18 at 15:17
  • jorge even removing what u suggested but still nothing – The Dead Man Oct 30 '18 at 15:17
  • My last suggestion it's to create a live version so I can have a look – Jorge Oct 30 '18 at 15:19
  • Now works no errors again thanks for your help @Jorge – The Dead Man Oct 30 '18 at 15:25
  • 1
    Glad to help, remember don't panic :D – Jorge Oct 30 '18 at 15:27
  • Yeah man , I have one last question I have section where I hide data, using `ngbCollapse` when I run `ng test` I get the following error `Failed: Template parse errors: Can't bind to 'ngbCollapse' since it isn't a known property of 'div'. ("` what do I need to change to get this working,?, on front end everything works as expected – The Dead Man Oct 30 '18 at 15:39
  • Probably due to a missing module in the tests – Jorge Oct 30 '18 at 15:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182806/discussion-between-user9964622-and-jorge). – The Dead Man Oct 30 '18 at 15:46