Тест интеграции компонентов с возвращением шасси - PullRequest
0 голосов
/ 05 мая 2018

Я пытаюсь провести интеграционное тестирование компонентов (т. Е. Включая события жизненного цикла Angular), но мне трудно высмеивать сервис с Jasmine, который предоставляет Subscribable.

Чтобы воспроизвести мой сценарий:

  1. ng new ng-comp-tests
  2. ng generate component my-screen
  3. ng generate service crud
  4. ng generate class item

Обновите класс до этого:

export class Item {
  constructor(public name: string) { }
}

Затем сделайте сервис похожим на:

export class CrudService {
  private thing = new Subject<Item>();

  constructor() {
    setInterval(() => { this.thing.next(new Item('Thing ' + Math.random())); }, 1000);
  }

  getThingObservable() {
    return this.thing.asObservable();
  }
}

Измените компонент так, чтобы он был таким (и включите его как главное в компонент приложения):

<p *ngIf="!!thing">{{thing.name}}</p>
export class MyScreenComponent implements OnInit, OnDestroy {
  public thing: Item;
  private thingSubscription: Subscription;

  constructor(private service: CrudService) { }

  ngOnInit() {
    this.thingSubscription = this.service
      .getThingObservable()
      .subscribe(t => { this.thing = t; });
  }

  ngOnDestroy(): void {
    this.thingSubscription.unsubscribe();
  }
}

И, наконец, измените спецификацию следующим образом:

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

  beforeEach(async(() => {
    const serviceSpy = jasmine.createSpyObj('CrudService', {
      getThingObservable: () => new Subject<Item>().asObservable()
    });

    TestBed.configureTestingModule({
      declarations: [ MyScreenComponent ],
      providers: [ { provide: CrudService, useValue: serviceSpy } ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MyScreenComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Это даст исключение для теста:

MyScreenComponent должен создать
[object ErrorEvent] thrown

Исключение не очень полезно, и консоль от Chrome также не полезна, потому что он показывает сокращенный журнал:

  • "Не удалось загрузить ng: ///DynamicTestModule/...ngfactory.js: запросы из разных источников ..."
  • "Не удалось загрузить ng: ///DynamicTestModule/...ngfactory.js: запросы из разных источников ..."
  • "Uncaught DOMException: не удалось выполнить 'send' ...."
  • «Ошибка при очистке компонента ... Невозможно прочитать свойство« отписаться »от undefined ...»

Топовый ответ на связанный вопрос предполагает, что я забыл сделать fixture.detectChanges() (что препятствует запуску ngOnInit), но, как вы видите, у меня это есть в коде.

Здесь должно быть что-то еще не так, но что?

1 Ответ

0 голосов
/ 05 мая 2018

Ответ лежит в документации jasmine.createSpyObj(...) , где говорится о втором параметре (выделено мной):

Массив имен методов, для которых создаются шпионы, или Объект, ключами которого будут имена методов и значения returnValue .

В вашем коде вы предоставляете ложную реализацию для getThingObservable, например:

getThingObservable: () => new Subject<Item>().asObservable()

При этом getThingObservable шпион вернет лямбду , когда компонент вызывает его, у которого нет subscribe, который компонент пытается сделать, поэтому ngOnInit завершится неудачей в целом. ngOnDestroy дает сбой только как вторичный эффект.

Вместо этого вы должны напрямую передать returnValue, например:

getThingObservable: new Subject<Item>().asObservable()

Затем, когда компонент вызовет getThingObservable, он получит фактическую наблюдаемость, и все будет хорошо.

PS. Вы также можете упростить использование { of } from 'rxjs/observable/of':

getThingObservable: of<Item>()

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...