Angular HTTP-сервис - тесты не пройдены - PullRequest
0 голосов
/ 14 марта 2020

Я изучаю Angular и написал сервис, который просто получает некоторые данные, используя HttpClient . У меня много проблем с написанием модульного теста, который подтверждает, что служба успешно получает данные. Я опубликовал свой исходный код и тестовое значение c для службы.

example.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class ExampleService {

  constructor(private http: HttpClient) { }

  // get some sample data from an remote server
  getData() {
    return this.http.get('https://jsonplaceholder.typicode.com/todos/1');
  }
}

example.service.spe c .ts

import { TestBed } from '@angular/core/testing';

import { ExampleService } from './example.service';
import {HttpClientTestingModule} from '@angular/common/http/testing';

describe('ExampleService', () => {
  let service: ExampleService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule]
    });
    service = TestBed.inject(ExampleService);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  // this is the test that fails
  it('getData should return the correct value',
    (done: DoneFn) => {
      service.getData().subscribe(value => {
        console.log('test never reaches this line');
        // tslint:disable-next-line
        expect(value['userId']).toBe(1);
        done();
      });
    });
});

Сбой теста getData should return the correct value с ошибкой Error: Timeout - Async function did not complete within 5000ms. Я заметил, что тест никогда не входит в метод subscribe(). Действительно странная вещь заключается в том, что когда я запускаю getData() вне среды тестирования, он успешно возвращает данные. Я часами пытался исправить это и пытался найти решение, но пришел с пустыми руками.

Ответы [ 2 ]

0 голосов
/ 15 марта 2020

Прежде чем ответить на ваш вопрос, следует отметить, что методы обслуживания не обязательно должны быть проверены модулем TestBed.configureTestingModule. Это только для тестирования компонентов или интеграционных тестов. Требуется протестировать завершенные angular жизненные циклы и создание DOM, но нам это не нужно для сервисов модульного тестирования.

Вместо этого вы просто создаете экземпляр своего сервиса в каждом тесте и присваиваете ему зависимости needs.

Чтобы выполнить юнит-тестирование сервисов с сетевыми запросами, вам нужно как смоделировать httpClient методы, используемые вашими сервисами (httpClient.get, httpClient.post, et c.), так и ответ сервера.

1) Чтобы смоделировать метод http.get , используемый в вашей службе, используйте jasmine.createSpyObj:

let httpClient: { get: jasmine.Spy };
let service: ExampleService;

beforeEach(() => {
  httpClient = jasmine.createSpyObj('HttpClient', ['get']);
  service = new ExampleService(<any> httpClient);
});

2) Чтобы смоделировать успешный ответ сервера , мы можем создать вспомогательную функцию, которая обернет данные в обещание. Возможно, вы захотите сохранить эту функцию в папке «test-utils», так как вы будете использовать ее во многих файлах spe c.

export function asyncData<T>(data: T) {
  return defer(() => Promise.resolve(data));
}

Если вам нужно смоделировать ошибку сервера, мы просто reject вместо resolve обещание:

export function asyncError<T>(errorObject: any) {
  return defer(() => Promise.reject(errorObject));
}

3) Теперь вы можете протестировать метаданные службы, которые выполняют сетевые запросы, определив ответ сервера в своем http-шпионе:

it('should return "Yay!"', () => {
  const expectedResponse = "Yay!";

  httpClientSpy.get.and.returnValue(asyncData(expectedResponse));

  service.getData().subscribe(response => {
    expect(heroes).toEqual(expectedHeroes, 'expected heroes')
  }, fail);
});
0 голосов
/ 15 марта 2020

Когда вы выполняете модульные тесты http-запросов, вы не можете использовать свой реальный сервис и сделать настоящий http-запрос. Таким образом, вы должны смоделировать свой сервис, создать поддельный сервис и подобный метод getData (), который также возвращает наблюдаемые и те же данные, что и реальный метод. Вы можете сделать это, создав класс-заглушку и используя Rx JS of, который является наблюдаемым и может использоваться вашим тестовым классом.

Ниже приведен пример того, как это сделать.

export class ExampleServiceStub {

  constructor() { }

  // get some sample data from an remote server
  getData() {
    return of(
        [
            {
                id: 1,
                name: 'Data name'
            }
        ]
    );
  }
}

Внутри of () вы можете поместить данные, которые вернет реальный http-запрос. Вы должны внедрить свой сервис-заглушку так же, как вы внедрили реальный сервис в тестовом классе.

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