Блок ошибок тестирования в subscribe, возвращающий observable- Angular-модульное тестирование

#angular #unit-testing #jasmine #karma-jasmine #angular7

#angular #модульное тестирование #jasmine #karma-jasmine #angular7

Вопрос:

Я хочу протестировать метод, возвращающий observable. Я могу протестировать метод, но я не могу охватить часть, возвращающую ошибку

home.component.ts

 import { Data } from './../model/data.model';
import { DataService } from './../services/data.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  data: Data[];
  errorMsg: any;
  constructor(private service: DataService) {}

  ngOnInit() {
    this.getData();
  }
  getData() {
    this.service.getData().subscribe(
      (data) => {
        console.log(data);
        this.data = data;
      },
      (err) => {
        this.errorMsg =err;
      },
    );
  }
}
  

Home.component.spec.ts

 import { Data } from './../model/data.model';
import { HttpClientModule } from '@angular/common/http';
import { HomeComponent } from './home.component';
import { ComponentFixture, async, TestBed, fakeAsync } from '@angular/core/testing';
import { DataService } from '../services/data.service';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/of';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { results } from '../model/home';

class MockMyService {
  public data: Data[];
  public getData(): Observable<Data[]> {
    this.data = results;
    return Observable.of(this.data);
  }
}

describe('HomeComponent', () => {
  let component: HomeComponent;
  let fixture: ComponentFixture<HomeComponent>;
  let dataService: DataService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [HomeComponent],
      providers: [
        {
          provide: DataService,
          useClass: MockMyService,
        },
      ],
      imports: [HttpClientModule],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
    }).compileComponents();
    fixture = TestBed.createComponent(HomeComponent);
    component = fixture.componentInstance;
    dataService = TestBed.get(DataService);
    fixture.detectChanges();
  });

  describe('Given the component is loaded', () => {
    describe('When getData returns mock data', () => {
      it('Then the data attribute has a length of 2', (done) => {
        dataService.getData().subscribe(
          () => {
            expect(component.data.length).toEqual(2);
            done();
          },
          (err) => {
            expect(component.errorMsg).toEqual(err);
          },
        );
      });
    });
  });
  it('testing error block', () => {
    dataService.getData().subscribe(
      (data) => {},
      (err) => {
      expect(component.errorMsg).toEqual(err);
      },
    );
  });
});
  

results.model.ts

 export const results = [
  {
    effectivefrom: '',
    effectiveto: '',
    externalname: 'SURVEY',
    id: 1,
    jhi_type: '',
    name: ' Survey',
    processstep: 1,
    status: 'Initialization',
  },
  {
    effectivefrom: '',
    effectiveto: '',
    externalname: '',
    id: 2,
    jhi_type: '',
    name: ' Survey',
    processstep: 1,
    status: 'Initialization',
  },
];
  

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

возвращаемая ошибка относится к объектному типу.

Как я могу преодолеть эту проблему? Заранее спасибо.

Ответ №1:

В этой ситуации, поскольку вы this.getData(); вызываетесь из ngOnInit() , у вас нет особого контроля над методом при его создании из MockSvc. Создайте 2 разных макета сервисов и используйте, как показано ниже

Попробуйте приведенный ниже код:

 import { Data } from './../model/data.model';
import { HttpClientModule } from '@angular/common/http';
import { HomeComponent } from './home.component';
import { ComponentFixture, async, TestBed, fakeAsync } from '@angular/core/testing';
import { DataService } from '../services/data.service';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/of';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { results } from '../model/home';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';

class MockMyService {
    public data: Data[];
    public getData(): Observable<Data[]> {
        this.data = results;
        return Observable.of(this.data);
    }
}

class MockMyServiceWithError {
    public data: Data[];
    public getData(): Observable<Data[]> {
        this.data = results;
        return new ErrorObservable(this.data);
    }
}

describe('HomeComponent', () => {
    let component: HomeComponent;
    let fixture: ComponentFixture<HomeComponent>;
    let dataService: DataService;

    describe('With Errored Response', () => {
        beforeEach(() => {
            TestBed.configureTestingModule({
                declarations: [HomeComponent],
                providers: [
                    {
                        provide: DataService,
                        useClass: MockMyServiceWithError
                    }
                ],
                imports: [HttpClientModule],
                schemas: [CUSTOM_ELEMENTS_SCHEMA]
            }).compileComponents();
            fixture = TestBed.createComponent(HomeComponent);
            component = fixture.componentInstance;
            dataService = TestBed.get(DataService);
            fixture.detectChanges();
        });
        it('should be created',()=>{
            expect(component).toBeDefined();
        })
        it('should have defined error message',()=>{
            expect(component.errorMsg).toBeDefined();
        })
    });
    describe('With Success Response', () => {
        beforeEach(() => {
            TestBed.configureTestingModule({
                declarations: [HomeComponent],
                providers: [
                    {
                        provide: DataService,
                        useClass: MockMyService
                    }
                ],
                imports: [HttpClientModule],
                schemas: [CUSTOM_ELEMENTS_SCHEMA]
            }).compileComponents();
            fixture = TestBed.createComponent(HomeComponent);
            component = fixture.componentInstance;
            dataService = TestBed.get(DataService);
            fixture.detectChanges();
        });
        it('should be created',()=>{
            expect(component).toBeDefined();
        })
        it('should have defined error message',()=>{
            expect(component.errorMsg).toBeUndefined();
        })
    });
});
  

Другой способ:

Или может быть что-то вроде приведенного ниже после создания service общедоступности внутри компонента:

 describe('Given the component is loaded', () => {
        // make constructor(public service: DataService) {}
        it('should expect defined error message',()=>{
            spyOn(compponent.service,'getData').and.returnValue(new ErrorObservable('Error code'));
            component.getData();
            expect(component.errorMsg).toBe('Error code')
        })
        it('should expect getData to be called',()=>{
            spyOn(compponent.service,'getData').and.callThrough();
            component.getData();
            expect(compponent.service.getData).toHaveBeenCalled();
        })
  });
  

Комментарии:

1. Это не работает после добавления всего кода, который он показывает в MockServiceWithError возвращает новую ошибку, поскольку observable не может быть назначен с этим. данные . ошибка=> Аргумент типа ‘Data[]’ не может быть присвоен параметру типа ‘(this: Observable<Data[]>, subscriber: Подписчик<Данные[]>) => TeardownLogic’. Тип ‘Data[]’ не соответствует подписи ‘(это: Observable<Data[]>, подписчик: Subscriber<Data[]>): TeardownLogic’

2. @AnilKumarReddyA : можете ли вы поделиться данными в results of import { results } from '../model/home'; ? Было бы хорошо, если бы это был просто hard-coded макет объекта для целей тестирования

3. @AnilKumarReddyA вы пробовали другой подход? Кроме того, ошибка, которую вы показываете, кажется, является некоторой type проблемой, нарушает ли она тестовые примеры? Можете ли вы поиграть с типом возвращаемого значения, потому что я не могу воспроизвести эту проблему

4. второй подход также не работает. Я уже пытаюсь возвращать разные типы данных. Не работает: (

5. @AnilKumarReddyA в чем ошибка при втором подходе? Это работает в моих случаях