Невозможно прочитать свойство отписаться от неопределенного: тестирование Angular2

Я пытаюсь протестировать компонент, который имеет метод ngOnDestroy(), который имеет все вызовы метода unsubscribe(). Но во время тестирования, когда я запускаю свой тестовый файл (спецификационный файл), он выдает ошибку:

cannot read property 'unsubscribe' of undefined

Я сделал следующий импорт в свой тестовый файл:

import { Subscription }   from 'rxjs/Subscription';

поэтому я думаю, что этого должно быть достаточно, чтобы получить все методы в подписке, но ошибка все равно есть. Кроме того, я попытался добавить «Подписку» в список «импорт», «объявления» и «поставщики» файла тестирования, но ошибка все еще есть.

Ниже приведен фрагмент кода:

//component
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription }   from 'rxjs/Subscription';
import {
 NinjaService } from '../../../../ninja.service';


 @Component({
 selector: 'ninja-files',
 templateUrl: './ninja-files.component.html',
 styleUrls: ['./ninja-files.component.css']
})
 export class ninjaFilesComponent implements OnInit, OnDestroy {

 showNinjaFiles: boolean = true;

 addFileSubscription: Subscription;

 constructor(private ninjaService: NinjaService) {
 ........
}

 ngOnInit() {
  this.addFileSubscription = this.NinjaService.AddedFile$
  .subscribe((fileFormat: FileFormat) => {
  console.log('File being added: ' + fileFormat.fileName); }

  ngOnDestroy() {
  this.addFileSubscription.unsubscribe();
}
}

Затем у меня есть тестовый файл для этого компонента следующим образом:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription }   from 'rxjs/Subscription';
import {
 NinjaService } from '../../../../ninja.service';
import { TestBed, async, fakeAsync ,ComponentFixture, } from '@angular/core/testing';
import { DebugElement }    from '@angular/core';
import { By }              from '@angular/platform-browser';
import {} from 'jasmine';

describe('Component: NinjaFiles', () => {

  let fixture: ComponentFixture<ninjaFilesComponent>;
  let component: ninjaFilesComponent;
  let ninjaServiceStub;

beforeEach( async(() => {
 //stub NinjaService
 let ninjaServiceStub= {};

 fixture = TestBed.configureTestingModule({
 declarations: [ ninjaFilesComponent],
}).createComponent(ninjaFilesComponent);
 component = fixture.componentInstance;

}));

it('Page Title', async(() => {
 let pageTitle = fixture.debugElement.query(By.css('.page-title'));
 expect(pageTitle).toBeTruthy();
}));

 it('Counting the files', () => {
  let fileCount= fixture.debugElement.query(By.css('.file-count'));
  expect(fileCount).toBeTruthy();
});

Когда я запускаю приведенный выше тестовый код, он выдает мне сообщение об ошибке «невозможно прочитать свойство« отписаться »от неопределенного» (что означает, что он не может определить объект подписки «addFileSubscription», который я определил в классе компонента.

Может ли кто-нибудь предложить обходной путь?


person Aiguo    schedule 28.10.2016    source источник
comment
Попробуйте вызвать fixture.detectChanges(); либо в beforeEach() в конце, либо в тесте в начале.   -  person Günter Zöchbauer    schedule 28.10.2016
comment
пробовал уже, не помогает! :(   -  person Aiguo    schedule 28.10.2016
comment
Не могли бы вы подтвердить, что ngOnInit() звонили?   -  person Günter Zöchbauer    schedule 29.10.2016


Ответы (2)


import { Subscription } from 'rxjs/Subscription';

Все это означает, что вы можете получить доступ к классу Subscription из файла класса ninjaFilesComponent.

Проблема в том, что addFileSubscription никогда не инициализируется. Для того, чтобы ngOnInit был вызван, вам нужно позвонить

fixture.detectChanges();

Помимо этого, другие проблемы, которые я вижу, это:

  1. Вы никогда не добавляете заглушку в провайдеры

    TestBed.configureTestingModule({
      providers: [
        { provide: NinjaService, useValue: ninjaServiceStub }
      ]
    })
    
  2. Вам действительно нужно что-то реализовать в заглушке

    let ninjaServiceStub = {
      AddedFile$: Observable.of(new FileFormat(...))
    }
    
  3. Вы неправильно используете службу в компоненте

    this.NinjaService.AddedFile$
    // should be
    this.ninjaService.AddedFile$
    // lowercase
    
person Paul Samsotha    schedule 29.10.2016
comment
спасибо за предложение @peeskillet! Еще один вопрос: «FileFormat» здесь — это интерфейс, поэтому я не могу использовать что-то вроде «AddedFile$: Observable.of(new FileFormat(...))» в моем ninjaServiceStub. У вас есть предложение, как создать наблюдаемый интерфейс? - person Aiguo; 29.10.2016
comment
Вам не нужно использовать класс. Какой бы ни была структура интерфейса, просто используйте литерал объекта, например { whatever: "properties", it: "has" } - person Paul Samsotha; 29.10.2016
comment
прочитайте это, чтобы лучше понять, как работают типы машинописи. - person Paul Samsotha; 29.10.2016

Добавление fixture.detectChanges(); к моим тестам решило эту проблему, с которой я столкнулся при запуске тестов с использованием Angular 2 CLI с Material Design.

Спасибо за обходной путь!

person Headcult    schedule 13.01.2017