Служба Angular 6 не может пройти модульные тесты с (NullInjectorError: нет поставщика для HttpClient!)

Я пытаюсь выполнить модульное тестирование в angular 6, когда запускаю `ng test '

Я получаю следующую ошибку

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)

Вот файл со спецификациями службы

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

});

Это файл usersevice ts

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.');
  }

}

Я пробовал другое решение из stack oveflow, но ничего не работает, я пробовал даже это решение здесь угловые ошибки модульного теста 5

Но, к сожалению, в angular 6 ничего не работает.

Что я делаю не так, любая помощь будет оценена ????

Я полагал, что ваша проблема зависит от определения TestBed, на котором вы определяете Testbed перед каждым тестом, и оставьте его пустым.

Jorge 30.10.2018 15:55

TestBed, настроенный внутри области describe, вызывается с пустым литералом объекта. Скопируйте литерал объекта из начальной настройки TestBed во вторую.

The Head Rush 30.10.2018 15:56

@Jorge, можешь показать мне, как это сделать правильно? Я просто манекен здесь, в модульном тесте, это мой первый модульный тест, хотя lol: P

The Dead Man 30.10.2018 16:00
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
3 485
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я полагал, что ваша проблема зависит от определения TestBed, которое вы делаете дважды, возможно, это проблема:

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

});

Должно получиться так:

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

});

позвольте мне проверить, я скоро вернусь

The Dead Man 30.10.2018 16:07

Протестировано с вашим решением, карма возвращает ту же ошибку: Error: StaticInjectorError(DynamicTestModule)[HttpClient]: StaticInjectorError(Platform: core)[HttpClient]: NullInjectorError: No provider for HttpClient!b Я даже заставил протестировать только эту функцию, добавив f для подписки fsubscribe

The Dead Man 30.10.2018 16:13

Еще одна вещь, которую я заметил: удалите модуль HttpClient, оставьте только HttpClientTestingModule, я обновлю пример

Jorge 30.10.2018 16:14

@ user9964622 Оставьте только тот раздел TestBed.configureTestingModule, который идет до каждого, но с правильным импортом

yurzui 30.10.2018 16:17

Хорхе даже удалил то, что ты предлагал, но все равно ничего

The Dead Man 30.10.2018 16:17

Мое последнее предложение - создать живую версию, чтобы я мог посмотреть

Jorge 30.10.2018 16:19

Теперь снова работает без ошибок, спасибо за помощь @Jorge

The Dead Man 30.10.2018 16:25

Рад помочь, помните, не паникуйте: D

Jorge 30.10.2018 16:27

Да, мужик, у меня есть последний вопрос, у меня есть раздел, в котором я скрываю данные, используя ngbCollapse, когда я запускаю ng test, я получаю следующую ошибку: Failed: Template parse errors: Can't bind to 'ngbCollapse' since it isn't a known property of 'div'. (", что мне нужно изменить, чтобы это работало,?, В интерфейсе все работает, как ожидалось

The Dead Man 30.10.2018 16:39

Вероятно из-за отсутствия модуля в тестах

Jorge 30.10.2018 16:41

Позвольте нам продолжить обсуждение в чате.

The Dead Man 30.10.2018 16:46

Другие вопросы по теме