Тест не пройден, когда данные наблюдаемы, но работают как переменные. (Ожидал шпиона, но получил неопределенность) - PullRequest
0 голосов
/ 19 января 2020

Это игрушечный пример, имитирующий некоторые ошибки тестирования в большом файле. В этом файле у меня есть коллекция кнопок, которые либо открывают определенные дочерние компоненты (модалы), либо запускают методы компонентов в зависимости от данных. В этом примере это всего лишь одна кнопка.

Я хочу написать несколько тестов для этих условий.

Обратите внимание, что некоторые вещи задают c для моей среды, например, ModalComponent - это пользовательский компонент, который открывает всплывающее окно. У него есть некоторые свойства и методы, но на самом деле единственная важная вещь - это то, что у него есть метод openModal (), который открывает объект. В этом игрушечном примере он ничего не делает.

У меня есть много вспомогательных методов и тестовых настроек, которые являются частью моего приложения, но не очень актуальны здесь, такие как TestModule (содержит общий импорт, объявления и провайдеры практически для каждого файла), queryDataId (запрашивает идентификатор для пользовательских элементов) и configureTestBedSuite () (устанавливает testBed, чтобы он выполнялся быстрее: https://www.npmjs.com/package/ng-bullet)

Итак в чем проблема? Сбой, когда я делаю buttonCollection $ Наблюдаемым. ie заверните в "из", как чуть ниже. Но мне нужно, чтобы это было Observable в главном файле.

buttonInfo$ = of({  
    buttonClick: () => this.myTestModal.openModal()
  });

), затем происходит сбой с

Ошибка:: ожидал шпиона, но получил неопределенное значение. Использование: Ожидайте (). ToHaveBeenCalled ()

Однако, если я просто создаю нормальное поле ie

buttonInfo = {  
    buttonClick: () => this.myTestModal.openModal()
  };

, тогда оно работает.

Не совсем уверен, почему это Это и я поставил точки останова в приложении, и оно, безусловно, вызывает функцию и попадает в строки кода. Кроме того, приложение работает, как и ожидалось.

Файл TS

import { ViewChild, Component } from '@angular/core';
import { ModalComponent } from '@my-library/modal';
import { of } from 'rxjs';

@Component({
  selector: 'ps-trial',
  templateUrl: './trial.component.html'
})
export class TrialComponent {
  @ViewChild('myTestModal') myTestModal: ModalComponent;

  buttonInfo$ = of({  // when I change this from an Observable to a regular variable the test works.
    buttonClick: () => this.myTestModal.openModal()
  });     
}

Шаблон

<ng-container *ngIf="buttonCollection$ | async as buttonCollection">

  <my-icon-button data-id="btnSaveModal" (button-click)="buttonCollection.buttonClick()">
  </my-icon-button>

  <ps-my-test-modal #myTestModal input="'input'">
  </ps-my-test-modal>

</ng-container>

И мой тест

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, Input } from '@angular/core';

import { TestModule, queryDataId, configureTestBedSuite } from '../../../../test';
import { TrialComponent } from './trial.component';

describe('TrialComponent', () => {
  @Component({
    selector: 'ps-my-test-modal',
    template: '<div>Mock Modal</div>'
  })
  class MyTestModal {
    @Input() input: string;
  }

  let fixture: ComponentFixture<TrialComponent>;
  let component: TrialComponent;

  configureTestBedSuite();  

  beforeAll(async () => {
    TestBed.configureTestingModule({
      declarations: [TrialComponent, MyTestModal],
      imports: [TestModule],
      providers: []
    });
    await TestBed.compileComponents();
  });

  beforeEach(async () => {
    fixture = TestBed.createComponent(TrialComponent);
    component = fixture.componentInstance;

    component.myTestModal = {
      openModal: jasmine.createSpy('openModal')
    } as any;
    fixture.detectChanges();
    await fixture.whenStable();
  });

  fdescribe('save button', () => {
    it('should open modal',  () => {
      queryDataId('btnSaveModal', fixture).nativeElement.click(); // this is a helper method that searches elements by the data-id and simulates a click.
      expect(component.myTestModal.openModal).toHaveBeenCalled();
    });
  });
});

Я пробовал различные комбинации fakeAsyn c и tick или async / fixture.detectChanges () / await fixture.whenStable () или подписка на buttonCollection $ observable, но это всегда та же ошибка. И как только я удаляю "of ()" и конвертирую его, он работает нормально. Я также экспериментировал с созданием шпиона.

Мне кажется, что-то не хватает

...