Angular 7 Component Test использует оригинальный сервис вместо макета - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь протестировать компонент с внедренным сервисом.Я хочу предоставить имитационный сервис в моем тесте.Однако тест использует оригинальную службу вместо фиктивной (я знаю это, потому что я получаю ошибку «Нет поставщика для HttpClient!», А также у меня есть файл console.log в исходной службе, которая выводится в тесте).

Я могу исправить ошибку, импортировав HttpClientTestingModule, но это не исправляет тот факт, что вместо фиктивного используется оригинальный сервис.

Есть идеи, что я делаю неправильно?

Вот мой тестовый код.Угловая версия 7

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { HelloWorldComponent } from '../../app/components/hello-world/hello-world.component';
import { HelloWorldService } from '../../app/services/hello-world.service';

describe('HelloWorldComponent', () => {

  let component: HelloWorldComponent;
  let fixture: ComponentFixture<HelloWorldComponent>;
  let mockHelloWorldService;
  
  beforeEach(() => {

    mockHelloWorldService = jasmine.createSpyObj(['getHelloWorld']);
    
    TestBed.configureTestingModule({
      imports: [],
      declarations: [HelloWorldComponent],
      providers: [
        [{ provide: HelloWorldService, useClass: mockHelloWorldService }]
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(HelloWorldComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
	
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
  
});

ОБНОВЛЕНИЕ

Я попытался overrideProvider, и теперь я получаю сообщение об ошибке «Невозможно прочитать свойство« подписаться »на неопределенную»что-то вроде прогресса ...

Вот мой тестовый код

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { HelloWorldComponent } from '../../app/components/hello-world/hello-world.component';
import { HelloWorldService } from '../../app/services/hello-world.service';
import { of } from 'rxjs';

describe('HelloWorldComponent', () => {

  let component: HelloWorldComponent;
  let fixture: ComponentFixture<HelloWorldComponent>;
  let mockHelloWorldService;

  beforeEach(async(() => {
    mockHelloWorldService = jasmine.createSpyObj(['getHelloWorld']);
    TestBed.configureTestingModule({
      imports: [],
      declarations: [HelloWorldComponent]
    });
    TestBed.overrideProvider(HelloWorldService, { useValue: mockHelloWorldService });
    TestBed.compileComponents();

  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(HelloWorldComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Вот мой компонент

import { Component, OnInit } from '@angular/core';
import { HelloWorldService } from '../../services/hello-world.service';

@Component({
  selector: 'app-hello-world',
  templateUrl: './hello-world.component.html',
  providers: [HelloWorldService]
})
export class HelloWorldComponent implements OnInit {

  helloWorldMessage: any;
  constructor(private helloWorldService: HelloWorldService) { }

  ngOnInit() {
    this.getHelloWorldMsg();
  }

  getHelloWorldMsg() {
    this.helloWorldService
      .getHelloWorld()
      .subscribe((data) => {
        this.helloWorldMessage = data;
        }, err => this.handleErrorResponse('There was a problem loading the hello world message', err));
  }

  handleErrorResponse(errorMsg: string, error?: any) {
    console.log("There was a problem getting the message");
  }
}

А вот и мой сервис

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

import { environment } from '../../environments/environment';

@Injectable()
export class HelloWorldService {
  constructor(private http: HttpClient) { }

  getHelloWorld(): Observable<any> {
    console.log("Why is the test coming here when I provide a mock?");
    var getHelloWorldApiUrl = environment.apiUrl + "/api/v1.0/helloworld/GetHelloWorldMessageAuth";
    return this.http
    .get(getHelloWorldApiUrl);
  }
}

Ответы [ 2 ]

0 голосов
/ 05 января 2019

В приведенном выше коде я вижу две проблемы:

  • У вас есть дополнительный набор квадратных скобок в массиве поставщиков вашего TestBed.Я не думаю, что это является серьезной проблемой, это просто семантически неверно.
  • Когда вы предоставляете HelloWorldService в массиве провайдеров, вы указали useClass, но предоставили объект (который является тем, чтоjasmine.createSpyObj() производит), поэтому вы должны вместо этого указать useValue.

Надеюсь, это поможет.

Обновление:

Хорошо, вы пришли довольнодолгий путь!Вы исправили две проблемы, которые я изложил выше, выполнив overrideProvider() перед compileComponents(), как я предложил в комментарии к другому ответу, а также завернули beforeEach() в async().

.причина, по которой я попросил посмотреть весь другой код, была в том, чтобы я мог быстро поставить его в следующем StackBlitz для тестирования.Как вы можете видеть из этого StackBlitz, тест в настоящее время проходит.

Я добавил только одну строку в beforeEach(), чтобы объявить returnValue от вашего шпиона, чтобы подписка в вашем компоненте имела Observable для подписки.to:

mockHelloWorldService.getHelloWorld.and.returnValue(of('Test Message'));

Я добавил это перед вызовом fixture.detectChanges(), так как это вызовет ngOnInit(), и шпиону необходимо установить возвращаемое значение ДО выполнения ngOnInit(), чтобы он выполнялся правильно, а невыдает ошибку, которую вы видите.

Я также добавил строку в спецификации, чтобы показать, как вы можете проверить, что результат Observable правильно установлен в вашей компонентной переменной:

expect(component.helloWorldMessage).toEqual('Test Message');

Обратите внимание, что вы значительно усложняете свое тестирование, указав HelloWorldService в массиве поставщиков декларации вашего компонента.Если вы вместо этого предоставите эту услугу в качестве отдельного пользователя в корне, это сильно упростит ситуацию, включая тестирование.Подробности см. В Официальных документах .

0 голосов
/ 04 января 2019

Возможно, ваш HelloWorldService объявлен в поставщиках компонентов.Поэтому вам нужно использовать https://angular.io/api/core/testing/TestBed#overrideComponent для замены провайдера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...