Как протестировать карту и tap pipe из RXJS в Angular

Я хочу протестировать свой код ниже, но я не уверен, как протестировать функции карты и касания (из RXJS). Должен ли я сделать макет, использовать шпиона?

Должен ли я вообще их тестировать? У меня есть привычка получать 100-процентное покрытие только для достижения этой цели (100-процентное покрытие), но я узнаю, что 100-процентное покрытие не всегда необходимо или полезно. Но в этом случае карта и тап очень важны для этой функции. Буду очень признателен за любой совет, спасибо.

Я использую Ангуляр 9.

Красные линии не проверены.

введите здесь описание изображения


person ineedtoknow    schedule 02.03.2020    source источник
comment
Да, вам нужно заглушить вызовы HttpClient, что описано в документации по тестированию. Затем вы можете создать шпион для регистратора. Начните с этого. При этом оператор карты не нужен в вашем коде.   -  person Alexander Staroselsky    schedule 02.03.2020
comment
Вы также можете использовать angular.io/api/core/testing/fakeAsync. чтобы убедиться, что ваша асинхронная работа завершена во время теста.   -  person Freddy    schedule 02.03.2020


Ответы (1)


Да, получение 100% охвата, вероятно, не лучшая идея, но это хорошая цель, к которой стоит стремиться.

Как я вижу, ваша служба выполняет HTTP-запросы, следуйте этому руководству для тестирования: https://medium.com/better-programming/testing-http-requests-in-angular-with-httpclienttestingmodule-3880ceac74cf.

И да, вам придется издеваться над loggingService;

Что-то вроде этого:

import { TestBed } from '@angular/core/testing';
import { CoursesService } from './courses.service';
import { HttpClientTestingModule,
         HttpTestingController } from '@angular/common/http/testing';
... // the rest of your imports

describe('TemplateService', () => {
  // We declare the variables that we'll use for the Test Controller and for our Service
  let httpTestingController: HttpTestingController;
  let service: TemplateService;
  let mockLoggingService: any;
  
  beforeEach(() => {
    // 'loggingService' is for your own sanity and the array are all of the public methods of `loggingService`
    mockLoggingService = jasmine.createSpyObj('loggingService', ['logger']);
    TestBed.configureTestingModule({
      providers: [
                  TemplateService,
                  // every time the test asks for LoggingService, supply this mock
                  { provide: LoggingService, useValue: mockLoggingService },
     ],
      imports: [HttpClientTestingModule]
    });

    // We inject our service (which imports the HttpClient) and the Test Controller
    httpTestingController = TestBed.get(HttpTestingController);
    service = TestBed.get(TemplateService);
  });

  afterEach(() => {
    httpTestingController.verify();
  });

  // Angular default test added when you generate a service using the CLI
  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('should make a get call for getTemplates and log', () => {
    const mockTemplates: Template[] = [/* you know how a template should look like so mock it*/];
   // make HTTP call take flight
    service.getTemplates().subscribe(templates => {
      expect(templates).toEqual(mockTemplates);
      expect(mockLoggingService.logger).toHaveBeenCalledWith(`User viewed templates: ${templates}`);
    });
   
   // have a handle on the HTTP call that is about to take flight
   const req = httpTestingController.expectOne(/* put the unique url of this method's get request that only you know of */);

   expect(req.request.method).toEqual('GET');
   // send this request for the next HTTP call
   req.flush(mockTemplates);
  });

  it('should make a get call for getTemplateById and log', () => {
    const mockTemplate: Template = {/* you know how a template should look like so mock it*/};
   // make HTTP call take flight
    service.getTemplateById(1).subscribe(template => {
      expect(template).toEqual(mockTemplate);
      expect(mockLoggingService.logger).toHaveBeenCalledWith(`User viewed template: ${template}`);
    });
   
   // have a handle on the HTTP call that is about to take flight
   const req = httpTestingController.expectOne(/* put the unique url of this method's get request that only you know of */);

   expect(req.request.method).toEqual('GET');
   // send this request for the next HTTP call
   req.flush(mockTemplates);
  });
});

Боковое примечание: ваши maps ничего не делают в обеих функциях, и их можно удалить. Они просто возвращают то, что получают, и ничего не трансформируют.

person AliF50    schedule 02.03.2020
comment
Спасибо за ответ и статью, и я ценю ваше замечание о том, что карты не нужны, я этого не осознавал. - person ineedtoknow; 02.03.2020