Макет директивы библиотеки из angular

#angular #jasmine #flatpickr

#angular #jasmine #flatpickr

Вопрос:

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

 // component.spec.ts
@Directive({
    selector: 'mwlFlatpickr',
})
class mwlFlatpickr implements OnDestroy{
  @Input('mwlFlatpickr') public x: any;
  @Input('convertModelValue') public y: boolean;
  @Input('dateFormat') public z: string;
  public ngOnDestroy(): void {}
}

describe('Component', () => {
  let component: Component;
  let fixture: ComponentFixture<Component>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        mwlFlatpickr
      ],
      imports: [
         // other modules
      ],
      providers: [
        // my services
      ]
    })
      .compileComponents();
  }));
  beforeEach(() => {
      fixture = TestBed.createComponent(CreateTaskComponent);
      component = fixture.componentInstance;
  });
  

HTML:

 // component.html
 <input type="text" class="floating-label-field" mwlFlatpickr [convertModelValue]="true" dateFormat="d.m.Y" formControlName="dueDate">
  

Моя проблема в том, что компонент использует реальный mwlFlatpickr, который выдает ошибку в его onDestroy (экземпляр компонента не определен, но это выходит за рамки моих тестов)

  TypeError: Cannot read property 'destroy' of undefined
    at FlatpickrDirective.ngOnDestroy (angularx-flatpickr.js:330)
    at executeOnDestroys (core.js:14123)
    at cleanUpView (core.js:14030)
    at destroyViewTree (core.js:13799)
    at destroyLView (core.js:13981)
    at RootViewRef.destroy (core.js:14836)
    at ComponentRef$1.destroy (core.js:33986)
    at ComponentFixture.destroy (testing.js:423)
    at UserContext.<anonymous> (component.spec.ts:160)
    at ZoneDelegate.invoke (zone-evergreen.js:364)
  

ошибка возникает при очистке, поэтому тест не имеет значения. Представьте it , что это просто:

  it('should not throw an error', () => {
    expect(component).toBeDefined();
 });
  

Я немного ошарашен. Все учебные пособия и темы, которые я нашел, решали издевательскую директиву таким образом (и она отлично работает с каналами)
Класс директивы объявляется как:

 export declare class FlatpickrDirective implements AfterViewInit, OnChanges, OnDestroy, ControlValueAccessor
  

естественно, я попытался изменить имя на это и также реализовал другие инструменты — та же ошибка, компонент не использует мой mockDirective

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

1. Вы пробовали ng-mocks ? Помогает с этим материалом

Ответ №1:

Он использует real mwlFlatpickr , потому что, держу пари, у вас есть FlatpickrModule в вашем imports массиве in TestBed.configureTestingModule или a SharedModule , который импортирует FlatpickerModule , и он использует фактическую реализацию вместо макета, который вы предоставляете. Попробуйте удалить FlatpickrModule или подозреваемый SharedModule из imports .

Если вы не хотите удалять SharedModule from imports , вам придется переопределить директиву с помощью overrideDirective . https://angular-2-training-book.rangle.io/testing/components/injecting-dependencies/overriding