【问题标题】:Angular 5 service failing to pass unit tests with (NullInjectorError: No provider for HttpClient!)Angular 5 服务未能通过单元测试 (NullInjectorError: No provider for HttpClient!)
【发布时间】:2018-07-12 08:39:35
【问题描述】:

我在运行单元测试时不断收到以下错误

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

api.service.ts

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

@Injectable()
export class ApiService {

  constructor(private http: HttpClient) { }
  url = './assets/data.json';

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

api.service.spec.ts

import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { ApiService } from './api.service';

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

  it('should get users', inject([HttpTestingController, ApiService],
      (httpMock: HttpTestingController, apiService: ApiService) => {
        expect(apiService).toBeTruthy();
      }
    )
  );
});

我不明白出了什么问题,因为我已将 HttpClient 包含在 api.service.ts 中,该服务在浏览器中运行。

这是在一个名为 MapComponent 的组件中直接调用的,并且是在 HomeComponent 内部调用的。

Chrome 63.0.3239 (Mac OS X 10.13.3) HomeComponent expect opened to be false FAILED
    Error: StaticInjectorError(DynamicTestModule)[ApiService -> HttpClient]: 
      StaticInjectorError(Platform: core)[ApiService -> HttpClient]: 
        NullInjectorError: No provider for HttpClient!

【问题讨论】:

    标签: angular unit-testing typescript angular5


    【解决方案1】:

    尝试将您的 inject 包装在 async 中,如下所示:

    import { TestBed, async, inject } from '@angular/core/testing';
    import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
    import { ApiService } from './api.service';
    
    describe('ApiService', () => {
        beforeEach(() => {
          ...
        });    
    
      it(`should create`, async(inject([HttpTestingController, ApiService],
        (httpClient: HttpTestingController, apiService: ApiService) => {
          expect(apiService).toBeTruthy();
      })));
    
    });
    

    别忘了从@angular/core/testing 导入async。

    我在这方面取得了很好的成功。这是与我使用HttpClientTestingModule 的单元测试和我的单元测试唯一不同的地方。

    【讨论】:

    【解决方案2】:

    "NullInjectorError: No provider for HttpClient!" 的原因是未解决的依赖关系。在这种情况下缺少HttpClientModule。

    在您的 .service.spec.ts 文件中添加

      imports: [
            HttpClientTestingModule,
        ],
    

    您可能会注意到我写的是 HttpClientTestingModule 而不是 HttpClientModule。原因是我们不想发送实际的 http 请求,而是使用测试框架的 Mock API。

    【讨论】:

    • 不要忘记在 app.module.ts 中进行同样的更改(Angular 5 上下文)。
    • 但是他已经在他的.service.spec.ts中导入了HttpClientTestingModule,如上图所示?
    • @Marius 您还需要将其添加到 TestBed 配置对象的导入数组中,如答案所示
    • 嗨 JP07,我只是想问一下,如果我在构造函数中注入 private changeDetector: ChangeDetectorRef,那么是否还需要在规范文件中模拟此服务。我问这个是因为我是 Angular 的新手。我不知道。请帮忙。
    【解决方案3】:

    像这样简单地添加,

      beforeEach(() => {
        TestBed.configureTestingModule({
          imports: [
            HttpClientModule,
          ],
        }).compileComponents();
      });
    

    【讨论】:

    • 谢谢,这解决了我的问题!顺便说一句,我不喜欢有角度的测试方式,因为它非常阴暗——这是我遇到的问题的第 5 个 stackoverflow 主题这一事实告诉我,以正确的方式编写这些测试非常复杂。我不知道我是否只是需要更多地了解角度测试或其他人因为他们的测试机制是blaah而感到沮丧。
    【解决方案4】:

    我有导入 HttpClientModule and HttpClientTestingModule 模块解决了我的问题。

    import { HttpClientTestingModule } from '@angular/common/http/testing';
    import {HttpClientModule} from '@angular/common/http';
    
      imports: [
            HttpClientModule,
            HttpClientTestingModule
          ]
    

    【讨论】:

    • 这些文件是从哪里导入的?
    • 您需要在组件规范中导入这些文件。
    猜你喜欢
    • 2019-04-03
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    相关资源
    最近更新 更多