Проблемы с spyService и throwError () в модульном тесте Angular / Jasmine; - PullRequest
0 голосов
/ 11 сентября 2018

У меня проблемы с издеванием над сервисом, который возвращает ошибку в файле модульного теста компонента.Мое приложение написано на Angular 6 с TypeScript, а мои модульные тесты написаны на Jasmine.

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

export class CylindersListComponent implements OnInit, OnDestroy {

public isLoading: boolean = true;

  public ngOnInit(): void {
      // do stuff ... I have removed some code here
      this.loadCylinderList();
  }

  public loadCylinderList() {
    this.cylindersService.getCylinderList().subscribe((res: any) => {
      this.cylinders = res;
      // do stuff ... I have removed lots of code here
      this.isLoading = false;
    }, (error: any) => {
      this.isLoading = false;
      throw new Error(error);
    });
  }
}

Я хочу смоделировать вызываемый метод loadCylinderList, а cylindersService.getCylinderList возвращает ошибку.Таким образом, как только это будет сделано, я хочу заявить (или убедиться), что свойство isLoading имеет значение false.Теперь у меня настроен модульный тест следующим образом, но, похоже, он не работает (или, скорее всего, я неправильно реализовал тест).Я снова свернул код или поставил ... туда, где возвращаются данные.

describe('CylindersListComponent', () => {
let fixture: ComponentFixture<CylindersListComponent>;
let instance: CylindersListComponent;

const spyCylinderService = jasmine.createSpyObj<CylindersService>(
'CylindersService', ['getCylinderList', 'getListPaged']);

spyCylinderService.getListPaged.and.returnValue(observedData); // observedData is set earler in the file 


beforeEach(async(() => {
    // inject the spies. We use override component because the service is injected
    // in component not in the module. (deeper level)
    TestBed.overrideComponent(CylindersListComponent, {
      set: {
        providers: [
          {provide: CylindersService, useValue: spyCylinderService}
        ],
        template: '<input #filter>'
      }
    })
    // prepare CylinderComponent for the tests
    // Allows overriding default providers, directives, pipes
      .configureTestingModule({
        imports: [...],
        declarations: [
          CylindersListComponent
        ],
        schemas: [CUSTOM_ELEMENTS_SCHEMA]
      })
      .compileComponents().then(() => {
      // arrange
      fixture = TestBed.createComponent(CylindersListComponent);
      instance = fixture.componentInstance;
      spyCylinderService.getCylinderList.and.returnValue({...});
    });
}));

it('should be false after error while loading data', () => {
    // arrange
    spyCylinderService.getCylinderList.and.throwError('error');
    instance.isLoading = true;
    spyOn(instance, 'loadCylinderList' as any).and.callThrough();

    // act
    fixture.detectChanges();
    expect(instance.isLoading).toBe(false);
});

Это звучит как очень открытый вопрос, и я извиняюсь, но что я делаю неправильно с моим методом test / spyOn.Я уверен, что получаю неудавшийся тест / ошибку, так как моя реализация для поднятия / проверки ошибки неверна: spyCylinderService.getCylinderList.and.throwError('error');

Если кто-нибудь увидит, что я делаю неправильно, я был бы очень признателен.Ошибка в тестовой консоли заключается в следующем:

HeadlessChrome 0.0.0 (Mac OS X 10.12.6) CylindersListComponent isLoading should be false after error while loading data FAILED
    Error: error
    error properties: Object({ ngDebugContext: DebugContext_({ view: Object({ def: Object({ factory: Function, nodeFlags: 33800449, rootNodeFlags: 33554433, nodeMatchedQueries: 0, flags: 0, nodes: [ Object({ nodeIndex: 0, parent: null, renderParent: null, bindingIndex: 0, outputIndex: 0, checkIndex: 0, flags: 33554433, childFlags: 246016, directChildFlags: 246016, childMatchedQueries: 0, matchedQueries: Object({  }), matchedQueryIds: 0, references: Object({  }), ngContentIndex: null, childCount: 4, bindings: [  ], bindingFlags: 0, outputs: [  ], element: Object({ ns: '', name: 'cylinders', attrs: [  ], template: null, componentProvider: Object({ nodeIndex: 4, parent: <circular reference: Object>, renderParent: <circular reference: Object>, bindingIndex: 0, outputIndex: 0, checkIndex: 4, flags: 245760, childFlags: 0, directChildFlags: 0, childMatchedQueries: 0, matchedQueries: Object, matchedQueryIds: 0, references: Object, ngContentIndex: -1, childCount: 0, bindings: Array, bindingFlags: 0, outputs: Array,  ...
        at <Jasmine>

Обновление: я уверен, что я поднимаю ошибку неправильно, как если бы я вставил console.log в компоненттам, где обнаружена ошибка, в консоль ничего не записывается.

1 Ответ

0 голосов
/ 11 сентября 2018

Причиной может быть то, что isLoading обновляется асинхронно.Поэтому вам следует дождаться окончания всех обнаружений изменений и обновлений.

it('should be false after error while loading data', async(() => {
    // arrange
    spyCylinderService.getCylinderList.and.returnValue(Observable.throw('error'));
    instance.isLoading = true;
    spyOn(instance, 'loadCylinderList' as any).and.callThrough();

    // act
    fixture.detectChanges();
    fixture.whenStable()
      .then(() =>{
            expect(instance.isLoading).toBe(false);
       });    
}));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...